讨论C/S结构TCP服务器的算法(散分1000罗)

flywhc 2001-08-14 02:59:37
我好久好久没发过问了,几千分多的也用不了,再此散分,但只给谈出心得谈出水平的朋友。
1周内我将发几个新贴给分,至少散个1000分吧,但不给灌水的哦 :)

服务器里最常见的就是C/S结构的TCP服务器了,无论是B/S结构的WEB还是FTP server,都需要TCP服务器。
它总是一个端口用于监听,若干个端口用于数据通讯。为了应付复杂的应用,它总是使用多线程的模型。

由于TCP仅次于应用层,因此,假如你构件了一个高性能的TCP的C/S结构服务器,可以很方便的做出Web/FTP/Mail/IRC等等各种各样的服务器。因此这个话题是非常有意义的。

虽然理论很简单,但是,就象数据库一样优化算法是相当重要的。

多数服务器都是基于unix吧,虽然赚钱,但离我们玩编程的是不是远了点?
基于winnt/9x,我做过若干服务器,但觉得性能都不是很令人满意,觉得总是可以再优化。请大家讨论一下,我提几个问题:

1. 对于winsock,实际有好几种socket模式,阻塞、同步非阻塞(select)、异步非阻塞(WSAAsyncSelect)还有winsock2.0的WSASend系列overlapped I/O函数,你觉得哪个好呢?对应的算法呢?

哦,对,还有NT的complete ports,谈谈也好,不过不能在win9x用。

2. 对于多线程模型,如果每个用户都开个线程,耗资源太大了,而且对于单CPU情况下,线程越多,性能似乎也越差。但单线程显然性能也差,至少不能抢占更多的cpu时间。
我常用的简单方法是把监听线程单独拿出来,数据都在一个线程中处理。好处是减少同步的麻烦,而且直觉上觉得cpu专心处理一件事再处理下一件事也比同时处理每件效率高。但数据处理复杂的情况(比如大量数据库操作)线程就总是在等待状态,浪费了cpu耗用。
较好的是有个线程池,但算法却复杂,如果调度和同步太复杂占用太多cpu,那性能反而降低了。
谈谈你理想的多线程模型和算法吧?

3.分布模型。如果做到海量应用,一定要用分布式的。使用DCOM组件?分布的数据库服务器?IP自动转向?

4. 优秀的源码/推荐。当然是越简练性能越高越好了。

语言不限
...全文
443 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
dash 2002-01-13
  • 打赏
  • 举报
回复
好贴,收藏先
STW 2001-08-30
  • 打赏
  • 举报
回复
http://www.csdn.net/develop/article/10/10177.shtm

VCbear翻译的这篇文章特别不错, 建议看看.
colababy 2001-08-30
  • 打赏
  • 举报
回复
你们现在进展如何?
flywhc 2001-08-23
  • 打赏
  • 举报
回复
socket我是这样封装的:
class CTcpServer{
public:
Send(SOCKET s,LPBYTE pBuf, int len);
virtual OnReceive(SOCKET s, LPBYTE pBuf,int len)=0;
void Close(BOOL bWaitForSend);
}
简单吧 :)

至于应用层,我现在不考虑什么用户之类的,我写的不是聊天室。

至于原来那个VB的聊天室,我设计上不是用于服务器,因此也没有优化过,着重那些比较花的功能,普通用户喜欢漂亮容易上手的软件而不是速度。

关于buffer,我原来是把多次发送的数据合并到一个buffer里。你的意思大概是不合并,但如何保存若干个未发送的buffer指针呢?想必用链表了,发送完了再delete,用前要new。

我想了个办法,用缓冲池,预先分配几百个缓冲区而且用数组管理。我还在优化,可以用最少的指令数做到线程同步。思想是大数组模拟new/delete操作。因为我想设计的是个通用的服务器,要设想请求和发送的次数和大小都是无限多的。


不过这个东西太大,最近写烦了,换个东西,正在写个全新概念的木马…… :P
STW 2001-08-22
  • 打赏
  • 举报
回复
To flywhc(午夜蓝调)
这几天俺倒下去了, 又感冒又中暑 :)

这个有个overlapped I/O例程你可参考参考
http://www.vchelp.net/source/submit/http_download.htm

overlapped i/o的“完成例程”俺没有测试过, 不过在<WINDOW 2000 编程技术内幕>中有
一个简单的文件操作例程觉得很能说明问题. 另overlapped i/o模型与WSAAsyncSelect俺
没有觉得倒退呀, 他们都是基于事件消息, WSAAsyncSelect只是将消息投射到窗口, 其它
底子里的运作有什么不同俺也不太清楚, 但overlapped i/o明显地底层一些, 很明显的允
许对SOCKET并发操作(重叠), 模型, 俺想也就是按需分配吧, 比如完成端口模型, 虽然它
也是基于overlapped i/o, 但它更适合多用户及复杂操作的情况下使用.

缓冲区问题, 俺的做法是用C++设计一个自已的缓冲区类, 缺省是1K, HTTP请求头大多不
到512个字节, 基本一次性就能将所有数据接收并分析. 如果缓冲区宽度不够, 那每次按倍
数自扩展, 边解释边接受数据, 这样没有什么冲突呀. new操作用得不多.

WSARecv的buffer数组用完要不要DELETE, 这得看你如何用了, 它不过是一个字符指针和
长整数的复合结构, 你想重用就重用, 不重用就DELETE, 如果是大家共享的, 那就等差不
多再DELETE. 这主要看你的需求和设计. 另俺觉得HTTP的head和body没有必要分成二段,
这样平白无故增加了一次发送操作, 整个系统的发送操作也就增加了一倍, 不可取啊.

overlapped I/O,允许很多线程同时WSASend, 但在每一次完整送出之前不要破坏用户缓
冲区的数据, 所以俺连系统缓冲区都不用了, 无谓的数据拷贝. 你发送的数据超过系统缓
冲区这个工作由系统处理, 俺记得好象是系统直接取用户缓冲区发送而不再COPY进系统缓
冲区再发送(这样也不错). 你以前的做法很不对啊, 分段发送用移动指针就好呀, 干嘛需
要不断的new和copy呢...

还有你提及的socket所对应的结构体, 俺建立还是要精心设计和包装一下, 尽量分开
SOCKET底层操作和应用层操作, 意思就是说, 尽量将SOCKET操作(相对来说它是底层操作)
与服务器应用层隔离, 不要象你那样将一个用户与一个SOCKET捆绑在一起, 应用层最大限
度是对套接字句柄只读权限, 否则多线程情况下容易出现不可预测的错误.

为了尽量减少NEW或DELETE, 将公用数据设计成只读, 积累到一定程度定时一次性删除.
比如聊天室里的聊天信息就是一个例子. 俺觉得这些设计用完成端口实现不难, 用单纯
的overlapped I/O或完成例程真难应付有些较复杂的情形或需要尽可能资源优化的情形.
并不一定非得用完成端口模型, 但用别的真是觉得冗长. 用完成端口的话, 俺认为可节
省很多代码, 而将时间花在数据结构设计方面.

俺的链表就是普通的单向有序链表结构呀, 没有什么特别, 算法是折半插入和查询, 只
是多了个固定指针数组方便索引, 用固定指针数组占用内存小, 最大结点数也就是数组
下标. 还需要多次new和deletet操作来结点, 因为俺主要是针对查询优化目的.

今天就这样吧, 好累 :)) 有空看看俺的聊天室服务器, 提提意见, 正在测试中.
用的就是完成端口模型, 目前俺已将俺知道并认为可优化的技术都用了.
http://www.chaozhou163.com

s6283 2001-08-22
  • 打赏
  • 举报
回复
要做iis,不如看看Apache现成的源代码
flywhc 2001-08-20
  • 打赏
  • 举报
回复
up...

我看了overlapped I/O的completeRouting,好像可以把hEvent设置成一个结构体的指针,那一切矛盾都解决了!

<network programming for windows>的作者好像不会使用completeRouting,写的也简单,例子更是荒谬,只支持1个连接。

我写个测试程序看看……
colababy 2001-08-18
  • 打赏
  • 举报
回复
为什么不在UNIX/LINUX下做?
jacka 2001-08-17
  • 打赏
  • 举报
回复
各位,TCP服务器是个什么概念?
按我的理解,TCP并无C/S之分,只有应用层的(http, ftp,...)才有C/S之分.
你们讨论的好象都是socket应用,怎么和"TCP服务器"搭上了关系?
请指正.
STW 2001-08-17
  • 打赏
  • 举报
回复
To: flywhc(午夜蓝调)

俺以前真很常上惠多, 俺上汕头的PCUG, 也就是张伽主持的汕头惠多BBS, 昵称也是那时开始
用的. :) 但那时还没开始玩编程, 不过有些零碎编程语言学习, 但一直找不到兴趣点, 后来
上了INET, 就几乎再也没有上惠多了, 在INET泡了几年, 最终找到了俺的兴趣点, 也就是对
网络编程感兴趣, 但俺很慢入行入门, 所以积累不多, 好几年的上网基本花在TELNET-BBS下
面聊天灌水, 连HTML都是二三年前学开始的. :))

你的这文章提及的问题也是俺不久前很困惑的问题, 所以俺也就将俺刚刚知道到的一点儿说
出来跟大家交流.(更因为是你的原因, 俺以前都向你请教过关于网络方面的问题).

<WINDOWS 网络编程技术>中文版译得还算不错哦, 至少比VC++技术内幕第五版强多了...:)

你说写个IIS, 俺觉得你很有雄心...但怕一个人的力量有限, 毕竟它牵涉到太多的东东, 不过
如果咱们自编了个对之有信心的TCP服务器框架的话, 那可重用它扩展出更多的应用服务器. 俺
觉得应用服务器真是较有前途(包括钱途).

接正题, WSAAcceptEx()完全可以不用考虑使用, 因为WSAccept也足够应付, 如果应用完成端
口的话, 那WSAAcceptEx()可减少一个线程安排, 也就是你说的只有一个工作线程,Overlapped
IO 用Event事件, 在WIN下当然效率高, "每个线程只能同时监视64个socket"?, 而是由于
WSAEWaitForMultipleEvens函数的限制, 一次只能等待64个事件句柄的数组(而不是64个
SOCKET), 但完全可以使用多个数组.

HTTP应用方面, HTTP1.1的KEEP-ALIVE特性非用不可, 就是持续连接. 俺觉得HTTP反应慢就是
它的一次性TCP操作 :( ... 另一个就是数据冗长. HTTP1.1比较HTTP1.0在这二点上有相应的
新特性, KEEP-ALIVE和HTTP压缩传输特性. 俺只接触过KEEP-ALIVE, 还没接触过HTTP压缩.

另外你好象放弃不了WIN9X, WIN9X不能当服务器用的, 一定要用的话, 那最好另写一套SOCKET
操作, 现在的硬件真好便宜, 将WIN2000用于服务器将会越来越广泛.

至于纯Overlapped IO模型和完成端口模型, 俺建议你二种模型都写一遍, 那样你会真正体会到
到底哪一种较适应你的偏好, 要求高性能的话那完成端口模型是绝对无疑的, IIS也就是用完成
端口模型, 相反的, 俺倒觉得完成端口模型程序编制起来更清晰, 更灵活.

再说缓冲区, 这个就是得按你的应用协议设计, 俺前面提过自伸缩缓冲区就是要适用于不知道
接受数据大小的情形, Overlapped IO数据结构中有提供数据接受大小呀, 还有类似指针的偏
移量参数返回或输入(发送时).

在线用户管理可以说纯属数据算法问题. 俺很同意你的方法, 俺也编写过, 就是链表数组相结
合成为集合形式. 便用数组是方便高速索引, 使用链表是方面高效搜索, 使用有序链表, 搜索
或模糊搜索用折半查询效率很高. 毕竟用户登录和退出只有各一次, 但搜索却是没计量的.

c的new和delete在多线程情况下也容易出错, 所以你用数组方法很不错啊, 减少这类相关操作.

算法俺还是建议使用有序链表折半查询方法, 并按应用需要优化, 查询插入和查询删除一次性完成. 包括一次性完成大范围内的模糊查询.

今天就聊到这儿吧, 俺一般是玩通宵的, 上来讨论的时候正是俺要去觉觉的时候, 今天有点困 :)


wwwunix 2001-08-17
  • 打赏
  • 举报
回复
看来我得看看windows网络编程了。:-)
linuxzyy 2001-08-17
  • 打赏
  • 举报
回复
用3层模型?
flywhc 2001-08-17
  • 打赏
  • 举报
回复
to jacka: "TCP服务器"意思是“使用TCP协议的各种C/S应用之服务器端编程问题”

to STW: 以前我在北京的各个CFido都有id,wang haicheng/float pointer,
想必zhang jia对我仍然记忆犹新,那时候南北大战就是我跟他吵起来的……
不过有两年多没去过了。

写个IIS比较庞大,但写其中的Web Server还是能做到的,尤其最常用的功能,比如asp解释。
也就是我写的是个PWS,PWS在win9x里就能用呀!
HTTP1.1 的Keep-Alive的确不错,尤其在聊天室中 :)
我也没怎么看过有关压缩的http协议,是content-coding吧,太麻烦了,好像也没什么服务器支持。


*socket模型的问题:
很让我头痛的问题是每个socket关联数据的组织。每个socket必须有相应的缓冲区和属性。对于
winsock1.1,我只能用个链表来存储,每次都要以socket为索引值遍历搜索。

很高兴地看到overlapped i/o的事件模型提供了一种方法,能得到index,这样用数组的下标就
可以找到对应的缓冲区和属性的结构体。

而完成端口模型则提供了CompletionKey这个好东西,连数组索引都免了。

令人失望的是overlapped i/o的“完成例程”竟然连socket是什么都不提供。在MS的例子里居然
用全局变量,这样每次只能有一个socket操作,根本不实用。lpOverlapped结构体中的唯一不是
"Reserved"的变量hEvent在完成例程中没有任何意义。我想我理解上大概有点错误,“完成例程”
这个模型竟然没有一点价值。

由于我不想放弃win9x,毕竟普通用户用win9x的多,我要写给普通用户玩的东西,因此必须使用
overlappedIO的事件模型。
按照那本书上说,采用事件模型,每个线程只能等待64个事件.因为不可能同时执行多个
WSAEWaitForMultipleEvens
因此,我们必须为每64个socket就开一个单独线程……如果开到上百上千个socket的话,消耗很
大呀。比起来如果用原来的WSAAsyncSelect的消息驱动模型,一个线程可以监视任意多个socket,
这不是一种倒退吗?


*缓冲区的问题:
如果应用很简单,收之前就知道最多能收到多大的数据包,发之前也知道发多少而且一次发完,那
就不用讨论了。可是实际上没有这么简单的应用,尤其用Keep-Alive,要反复的接收请求-回应、
再次接收请求-回应……,而server push则需要多个线程频繁的多次发送。

对于接收缓冲区,我仍然不知道WSARecv的buffer数组到底有什么作用。在接受数据以前,我们不
可能预先知道数据最终有多长,缓冲区可能不够大,当缓冲不够大时,我就要new一个更大的缓冲,
把以前的数据拷进去,然后补上新的数据,好像一个栈;而且我们不知道接收到少个包才完成一个
请求,只能不断的补数据直到满足特定的条件,比如连续两个回车换行或长度达到content-lenght
(如果是其他协议就不知道是什么了),这就是接收数据时什么时候才算“完成”的问题。上述方法
也要不断的new和copymemory,效率高不了,但我也没办法。 :(

对于发送缓冲区,缓冲区数组就有明显的意义了。以前我要把header和body合并再发出去,现在放
到数组里就好了。可是我仍然有个问题,这个缓冲区数组在用完以后可不可以就delete掉呢?如果
可以,假如这个缓冲区里的内容远比系统缓冲大,WSASend立刻返回,那些内容系统放哪里去了?
既然是overlapped I/O,是不是说可以很多线程同时WSASend?那么,如果各个线程同时发送的数
据的总量远超过系统缓冲区,那会怎么样?
按我以前的方法,就要有自己的一个发送缓冲区,每次发送都是补加到这个缓冲的末尾,如果缓冲
不够大,仍然是要new一个新的再copymemory,send函数每次发送这个缓冲的前面的一部分(就看
系统缓冲有多大),留下后半截,这样成了一个FIFO的缓冲区。造成的结果也是大量的new和
copymemory操作。 :(


可以看出,以前的异步非阻塞模型困扰我最大的有两点:
一是得到每个socket所对应的结构体,这个结构体里有我需要的自定义缓冲区指针和属性值,每次
都要遍历查找以及new/delete的操作。 -- 难道把socket的值也排序存放用二分查找?
二是发送和接收的缓冲区都要大量的new/copymemory操作,以应付断断续续的收/发包操作。
再考虑同步,性能如何就可想而知了。

如果被迫用这种方法,delete的缓冲区应该是可以重用而不必delete的。又有算法问题了。



用户管理上,其实我完全没有用VC作过,而是用类ASP脚本调用VB的集合组件完成,VB的集合组件
有自动索引的功能,这就是写个pws的好处,无论什么应用很短时间用脚本就能实现了。
不过如果用VC作组件一定效率提高很多。
你说的数组链表结合,还能实现排序和搜索,是否是这样:
class table{
CItem items[MAX_ITEMS];
table *pNext;
.....
}

如果把table当成一个数组,不够大小可以用pNext,可以很容易找到中点,但是排序插入却需要
copymemory了,尤其跨几个pNext指针……
allfresh 2001-08-16
  • 打赏
  • 举报
回复
强烈关注,
STW 2001-08-16
  • 打赏
  • 举报
回复
回复 flywhc(午夜蓝调):

你说的那本英文版本就是俺说的<WINDOWS 网络编程技术>中文版, 这本书是俺见过的WIN网
络编程最详尽及全面概述, 另有清华出的<WINDOWS SOCKET 网络程序设计大全>, 这本资料
性很强, 也是必备. 这二本中文版本在网上都可下载到, 你到搜索引擎找找. 前本的例程源
码也应能在网上找到.

WSAAcceptEX()在<WINDOWS 网络编程技术>中有描述, WSAAcceptEX()本来是WINSOCK1.1
的扩展函数并延伸至WINSOCK2.0或更高版本, 但<WINDOWS SOCKET 网络程序设计大全>中
并没有提及到微软的SOCKET扩展函数系列.

WSAAcceptEX()跟WSAAccept()的差别在于咱们需要为WSAAcceptEX()提供咱们手工建立的
新连接套接字, 而WSAAccept()返回的是系统自动建立的新套接字, 但WSAAcceptEX()除了
将你手工建立的套接字跟外部请求连接起来之外, 还负责接收第一个数据块, 现实中很多
C/S就是差不多是这样, 就是向服务器发出连接请求, 请求成功(也即连接成功)之后接着向
服务器提交验证数据(比如WEB服务器等等), WSAAcceptEX()将合二为一, 当然服务器端也
可以连接之后随即向客户端发送第一个数据(比如时间服务器, 只打比方, 时间服务器好象
是UDP的).

几乎同时向服务器请求连接的情形很多, 而LISTEN()函数的一个参数好象就是请求队列套
接字数量限制, 一般好象是5, 在这种情形之下俺做过测试, 服务器端预先建立一定数量的
预接受连接套接字(跟工作线程数相等即可), 接着同时向监听套接字发出完成端口操作请求,
之后用这几个工作线程来接收连接的完成操作消息, 几乎很常同时从LISTEN的5个队列中获
得1-3个连接, 所以俺认为, ACCEPT()和WSAACCEPT()这二个函数操性能还有提高的余地.

Overlapped I/O 和 基于Overlapped I/O的完成端口这二具异步操作模型让你脱离阻塞与
非阻塞的困惑, 按书上说, 就是模型跟模式没关, 俺前面说过, 模式只有阻塞与非阻塞二种,
完全利用WIN操作系统的消息和消息队列操作套接字, 并允许你二个线程同时操作在同一个套
接字上, 不管你几个线程同时读或同时写或又边写边读, 谁先谁后同WIN操作系统消息管理确
定, 这岂不是很诱人的事么 :) 在这里根本不需要轮询这个词汇, 要是管理数千上万的套接字
而用手工轮询并读写齐来, 俺觉得是很没效率的事.

关于套按字缓冲区, Overlapped I/O 并没有帮你管理缓冲区的, 但你完全可以不用系统为
套接字建立的缓冲区(可以通过setsockopt函数设定关掉系统缓冲区), 而完全使用咱们自定
义的可伸缩性并与咱们的应用协议相关的缓冲区类, 这样免除了系统缓冲区和用户缓冲区之间
的拷贝操作, 同时验证外面进入的数据合法性, 但你得保证在还没操作完成之前不能破坏缓冲
区数据.

线程池还是要自建, 就是预响应线程数组, 这个俺觉得没有什么好谈的, 一个CPU三四个线程
用户工作线程就足够了, 你找些系统进程线程观察软件看看去, IIS也不过几个线程罢了, 但
IIS也有线程池, 二个以上的线程数组就可以称为线池了. 去年和今年IIS4和IIS5都获得ZNET WEB服务器性能评测第一名. 谁说UNIX做为服务器一定高性能, 那微软的IIS服务器就足够说明
问题了, 扯那么多干嘛呢.

TransmitFile()也是微软件的SOCKET扩展函数之一, 它确实是发送静态数据的最好办法, 它
也可附带其它动态数据, 可定义在静态文件发送之前或之后或前后发送你想发送的附加数据,
比如HTTP响应头, 它也有它自已的灵活性.

俺个人看法, 不要奢望WIN和UNIX双兼容, 与于高性能需求是相矛盾的事, 象那个知名度最高
的免费WEB服务器不就是一个系统一套SOCKET操作过程函数么, 将所有的函数捆绑在起来就叫
跨平台. :)

数据库操作的等待, 俺这方面还没有多少经验, 如果数据库也有遵循完成端口模型操作或至少
事件之类模型, 那也同样可以不用等待. WIN的数据库如果没有事件或队列那样的操作, 俺觉
得不可想象. 对于事件消息通知方式, 耗时与否并不重要, 咱用户程序只管接受你的完成或失
败消息.

相比较于完成端口模型, 用纯粹的Overlapped I/O模型或完成例程来操作, 俺觉得编程人员需
要太于的精力花在事件设置, 程序编制有点冗长, 用Overlapped I/O模型附加完成例程(完成例
程跟完成端口是二码事), 虽然少了些繁锁, 但一般得用到SleepEX()函数, 那又会占用线程,
那又会产生产生线程数量和线程切换问题.

完成端口, 它本来也就是利用Overlapped I/O, 但在Overlapped I/O数据结构里面的事件句柄是不需要用到, 一般是NULL. 所以没有前面所说的繁锁, 相反的俺倒觉得用完成端口模式, 写
起程序来条理性很好! 关健部分在于里面的单句柄数据和单操作数据结构的设计(跟你的应用协议
议相关).

以是俺的理解, 各位高手有不同的看法请发表, 共同提高.
这次就说到这理吧. 这几天俺有点忙, 尽量争取上来讨论.

To WHC, 咱俩算是有缘人, 以前俺也常到网易, 多次跟你在讨论区擦身而过, 不过真的
碰在一起的倒很少. 这次终于...虽然在网上没有多少相遇, 但至少咱俩还通过电话,
俺是小贤. 记得吧? 俺可是很敬佩你哦, :) 俺的QQ是17688 有机会也可通过QQ交流.
向你学习!!

















纯粹使用咱们










flywhc 2001-08-16
  • 打赏
  • 举报
回复
原来是你。相信你以前也常用拨号BBS的,这样咱们以前更擦肩而过了。 :)
我的QQ号码比你的还小一些,16762;但很遗憾我现在不能用QQ,而且只能访问技术站点。

这么一大篇写得很精彩,佩服。:)
我刚下了那本书,发现几乎是逐句翻译的,翻译质量不太好。

我编程全凭爱好,想起些什么就写什么程序。非非聊天室扔下1年多没有再写。
前几个月忽然想写个IIS,而且不用MFC只用ATL,基本实现了ASP、COM组件的支持,当然也把push给加进去了。我的负载平衡的方法就是想利用DCOM。但感觉性能不好,稳定性差,因此想重写。同时也想,如果写个通用的TCP服务器,那写各种服务器不都是很容易了吗。


应该是AcceptEx()。感觉用处不大。我仍然认为,把Accept()放到一个有高优先级的单独线程里效率比较高,保证可以处理最多数量的并发请求。
不过Overlapped I/O 能够让不同的线程同时操作一个socket的话,真是不错。
可是看来Overlapped IO不过是用Event代替了消息循环。你认为效率就高了吗?而且每个线程只能同时监视64个socket的话显然满足不了应用。
完成端口再好,可我想在win9x下也能够用,就好像PWS...
我再看两天Overlapped I/O……


似乎照你的说法,一个线程就够了。
实际上不太现实。比如我用script解释,调用com组件。的确数据库操作支持事件驱动,然而在脚本里却只能用同步方式的数据库操作。异步事件驱动编写起来不如同步结构清晰,而且需要一些额外的代码。


既然缓冲区完全需要自己管理,在收/发的时候你并不知道需要多大的缓冲区才合适,需要动态更改缓冲区大小;还有其它的一些数据需要自己管理,而socket没有提供一个附属的指针提供管理的方法,就要考虑下面这个问题了:

===================================================================
 tarkey(天星) 回复于2001-8-15 16:34:44
如果做目前已经出现的SERVER我觉得没什么意思了。
不过我觉得TCP SERVER比较重要的问题还是对在线用户的管理问题。
维护一张HASH表,对所有在线用户的行为和状态进行统一管理。
其中搜索只类的算法还是需要好好设计设计的。
===================================================================

我以前做的时候就是用这样一个表来维护。比如
struct sockitem{
SOCKET s;
LPBYTE outBuf;
LPBYTE inBuf;
int nUserID;
.....
}
然后用个链表或数组管理。
当有一个socket事件的时候在这个表里查找到相应的sockitem

链表的缺点是要反复new/delete,heap操作耗时很多,查询速度也不快。于是我结合数组和链表:

struct socktable{
sockitem items[MAX_ITEMS];
socktable * pNext;
}

每次new一个socktable就相当于new了MAX_ITEMS次。而且不使用delete,每添加一个socket只是在表中搜索 items[n]->s == 0 然后复制。

不知道这种算法好不好。还有什么好方法?

请上面讨论过的朋友在http://www.csdn.net/expert/Topic/239/239980.shtm
留句话领分,否则只能等下星期结这个贴子时候了。
STW 2001-08-15
  • 打赏
  • 举报
回复
To 午夜蓝调:
按你的问题序列俺发表俺的个人看法;(下面的看法只限于WINNT或WIN2000)

1. TCP WINSOCK工作模式只有二种, 就是阻塞跟非阻塞.
模型就有好几种, 比如: 阻塞下的SELECT, 异步WSAAsyncSelect, 重叠IO模型,
完成端口重叠IO操作模型. 其中完成端口操作模型是最为高效率的模型, 适合用
于高并发即时通讯服务器需求. 要是做为服务器, 用WIN9X是不够的, 如果非用
不可, 那就只能选择重叠IO模型(并利用完成例程).

说到函数, 俺认为微软的WINSOCK扩展函数要用上, 其中二个较重要的:
WSAAcceptEX(): 一次性完成套接字连接和数据接收.
TransmitFile(): 基于WIN文件系统内核文件传输.

2. 线程模式, 当然是预开工作线程池最有效率. 线程需要开多少, 当然是在满足需求的
情况下尽量少以减少线程切换. 最理想是一个CPU一个线程, 但这当然是不满足能咱们
的要求. 线程模式跟WINSOCK工作模型是不能分开谈, 对于WIN的基于事件或消息编程来
说, 并不用需要开很多的线程来响应, 每个CPU有几个响应线程就够了. 最理想是拥有
是二个CPU以上工作(得做好线程同步工作). 你将监听工作独立开线程, 这种方法很常
用, 但用WSACCEPTEX的话, 就不用单独监听线程, 用完成端口操作, 它只管你完成了
没有, 完成的话就返回消息给你, 这样所有的工作线程都相似线程.

你提及的线程等待, 为什么有那么多的线程等待呢, 开那么多的线程来等待, 无疑是
增加每个CPU上的线程切换开销, 所以所有的操作都要用异步操作, 包括读文件, 才
能减少线程的等待并减少线程数. 使每一个线程一气呵成, 不要在中间等待, 让等待
的只是操作系统的异步操作完成消息.

3, 分布模型俺并不熟悉, 希望多听各位介绍...

4, WINDOWS网络编程技术这本书很好, 里面还有各种WINSOCK操作模型的例程源码, 包括
完成端口操作.

俺不是为分数来的, 而为了交流.













flywhc 2001-08-15
  • 打赏
  • 举报
回复
to colababy: 我的问题是做个WEB server, 比如IIS吧,好像就不能判断优先级了。
线程数量怎么算才合理呢? IIS的线程数好像是固定的?

to STW: 先说4, 你说的是<network programming for microsoft windows>吗?
我这里有本原版书,头儿从美国背来的,49.99$呢。不过一直懒得看,因为没有可以取印刷词汇的词霸 :P

没到找到WSAAcceptEX,只有WSAAccept。
不过如果自动Accept并接受数据的话,那不是不能控制最大连接数了?
实话说我以前只用过winsock1.1,好久没写过server了。
刚看了一下,Overlapped I/O 的确很不错,以前我要为每个none-blocking的socket开一对buffer,每接收一段数据就要重新copy一次buffer,用Overlapped I/O好像系统帮你管理buffer,直到数据完全接收/发送完,对吧?
完成端口又提供什么好处呢?帮你开好了线程?大概介绍一下吧

TransmitFile是直接发送文件都不需要读入缓冲区了,不过却不能处理数据了。

不管怎样,这些方法都使win下的socket编程离unix兼容越来越远了。使我们不能把一套c代码经过少量更改就用到unix上。
win下的这种消息或者事件驱动,会比unix方式的死循环查询+多线程式的效率高么?

不可能所有操作都没有等待,比如对外部数据库服务器操作或者一个很复杂的计算过程,在同时阻塞了消耗cpu很小的网络数据接收、发送操作。

按你的意思,是不是要把所有耗时操作都放到一个单独线程里,用队列排队这些任务,当完成时发回主线程一个消息或事件?就好像overlappd I/O那样?

这样的话线程数量就好订了。假设我们有1个cpu,主线程处理一切网络、磁盘操作,并全都用overlapped I/O,因此cpu耗用可以忽略;然后每个耗时任务开一个线程,每个线程都是个死循环,不断从一个FIFO的任务列表里读主线程交给的任务,完成后PostMessage主线程一个完成的消息。

或许我们应该可以增加每个耗时任务的线程数量,比如同时有几个脚本解释器在进行同步数据库操作(比如ASP脚本),同时从任务列表里读取任务。而不需要耗时的文件传送则用TransmitFile传送。

大家觉得,IIS会不会就是这样做的呢?

继续讨论……继续给分……问题不限于这几个
楼上几位到另一个贴子领分,无论你想不想要分 :)
tarkey 2001-08-14
  • 打赏
  • 举报
回复
最大线程的数量必须是确定的。
另外我认为网络连接的部分由UNIX/LINUX来做确实非常不错。
然后对数据处理和管理方面用VC来做是个理想的选择,但是两个是不同的操作系统,
怎么把综合两家之长呢?这就要用到JAVA了,JAVA只要有虚拟机,到哪儿都能用,
我们就可以通过JAVA,把VC做成的东西和UNIX/LINUX下开发出来的东西结合到一起了。

所以说,真正要开发一个大型的网络网络管理软件,不能单靠WIN或者UNIX/LINUX的。
而必须是靠两者结合起来运做。

colababy 2001-08-14
  • 打赏
  • 举报
回复
呵呵!开多少线程,这个数字的确不好确定,能不能最好是弹性的!根据来的请求的数量来确定。
不过,我这我可没试过。调度算法肯定是核心。呵呵!你就下班了?我还没上班呢!
加载更多回复(5)

4,356

社区成员

发帖
与我相关
我的任务
社区描述
通信技术相关讨论
社区管理员
  • 网络通信
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧