一个TCP-Socket-Block模式中-线程中,怎么使它进行多个工作?重叠? (100分)

  • 主题发起人 主题发起人 copy_paste
  • 开始时间 开始时间
C

copy_paste

Unregistered / Unconfirmed
GUEST, unregistred user!
TCP-Socket-Block模式中-线程中,怎么使它进行多个工作?
说得不知清楚不?我的意思是说在线程中的阻塞方式中,怎么样让它可以重叠使用,
如一个客户连接到服务端,服务端开启了一个线程与它交互。
当Client和Server正在发送文件期间,我想Client和Server又能够通讯,
这样它好像重叠了SocketHandle,能不能这样工作,各位不要说另开一个Socket,
作为发送文件流的用的。
 这好像是重叠操作吧,我对这方面不是很熟,请教各位了。
 
请看一下我在此贴中的回答,有不明白的再问我
http://www.delphibbs.com/delphibbs/dispq.asp?LID=838394
 
我先看看先,如果可以,就结帐
 
mywyn,你能不能简单说一下overlapped I/O操作不?
 
比如我在send file stream,有client消息来了,这时该怎么处理了。

procedure sendfile(filename; string);
begin
readfileToBuffer(filename, Buffer);
while not SendOver do
begin
RetLen := sendfileToClient(Buffer, 8K);
//send的过程中如果有client信息来了怎么办了
Inc(Buffer, RetLen);
end;
end;

而且同样客户端也是,正在接受server的filestream,它怎么切换到其它状态,先发其它消息
然后再回来收filestream了。
 
接收跟发送应处于两个不同的线程中,如果你是用overlapped I/O加完成例程,
当发生上述情况时,系统会给你记着。直到接收线程得到cpu时间片,系统调用你的
接收完成例程让你处理。不明白可以再问。
 
想了几天也没想通,:)
我的发/收已经是在使用线程了,如果再开线程的话,真是很大开销了,而且(还没试)如果
在线程中创建线程的话会不会死的很难看,我在线程中创建一个Form的话就会,我都是在Form
已经创建好了情况让再传给线程的,如果这样再开收/发线程,真是增大复杂性。我再想想。
 
我的意思是所有的收处于一个线程,所有的发处于一个线程。这才是重叠的
真正含义。如果再加上连接处理线程和主线程总共才4个线程,就可以承受
几百个连接(由于是win98不可能承受太多的连接),比起开几百个线程是不是
要好很多?
 
有FTP(一个命令连接,一个控制连接)吧,有控件,又容易实现,搞得这么复杂!
 
to brokensun:
据我所知,没有那个控件是使用重叠I/O技术的。如果你能找到请
告诉我一声。
 
重什么叠啊,根据copy_paste原需求用什么重叠啊?FTP难道不是这种方式工作的么?
 
to brokensun:
1.ftp是建立在tcp/ip上的,而windows又是通过winsocket实现tcp/ip的,可以说socket的
工作方式决定了ftp的工作方式,先把概念搞清楚。要想在window平台上建立
ftp服务,就必须采用重叠操作或完成端口操作,否则就不可能承受成千上万的连接。
可惜的是我所知的控件没有一个是采用这个技术的。当然,我指的是服务器程序,不是
客户端。
2.copy_paste的意思是在阻塞方式下进行重叠操作,这是行不通的。作为服务器程序
用阻塞方式绝对是个错误,所以我主要给copy_paste讲了win98下的重叠操作。
3.欢迎指正。
 
呵呵,是我没看清问题
服务器程序采用阴塞方式当然有它的用武之地,何谈绝对错误,ftp哪里是用了什么重叠,只是
用了两个连接而已,你不吓我哦~~~~,只是我看清copy_paste本意为没想再有一个连接(不知有
何难言之隐),所以再谈也没必要了
 
不错,开发主要是为了解决问题。但如果思路不对,那你开发越多错的越多,最后
还得重新来过。对于ftp服务器程序而言,用阻塞方式绝对行不通,这是我的经验教训,
如果我给他一个阻塞方式下的方案那才叫越领越歪。要想从socket层次开发服务器程序
不管是ftp服务还是web服务,重叠技术一定要精通,而不是粗粗了解。所以我在这儿
只能给copy_paste一个思路,也就是你说的让他粗粗了解了一个重叠,其余的就要
靠他自己了。
 
服务器程序如果是用来承受大量连接的,用阴塞方式绝对是错误。至于其余用途我
不清楚,也不敢乱说。
>>ftp哪里是用了什么重叠,只是用了两个连接而已
我不明白这是什么意思,按我的理解,这样的程序岂非只能接受两个连接?
 
哦,原来你一直在说我的程序设计中的来一个客户不应该用进程和阻塞方式去处理,我说怎么不
了解你的意图,这么笨。
在Delphi用的Socket运用中我只看到一个有个Overlapped的操作,就是TWinSocketStream.Read/Write中
但是它是用阻塞方式进行的,用非阻塞它就不支持,不过它的太过简单了。我看了一下
Overlapped(ReadFile, GetOverlappedResult)的帮助,我想问一下:是不是说在如果在
Send/Recv的过程中如果没有得到对I/O Socket的操作,那么就需要对SendOverlapped.hEvent and
RecvOverlapped.hEvent进行WaitFor直到它正确返回,通过GetOverlappedResult来得到它
Send/recv的返回结果?

最后我想说的是,我是在看Delphi中的MIDAS中的Scktsrvr and TSocketConnection,它里面使用
的就是我所说是这种模式,阻塞,一个线程响应一个客户,那么这么说来它只是适用于少用户量
的情况了,因我基本是接照它的方式来做的。
 
怪我没说清楚,不好意思。
我建议你用完成例程,而不是用事件通知方式。也就是说,不要对SendOverlapped.hEvent
赋值。因为WaitForMultipleObjects之类函数的限制,每个线程最多只能等待64个事件。
而且用完成例程,程序的条理比较清楚。(至少我这么认为)
另外,完成例程一般是和sleepex一起使用;GetOverlappedResult的功能也被完成例程
替代。
 
不好意思,我没看清你上面所说“例程”的意思,是说“写一个我要求的例子的程序吗?”
我刚看了一个http---一个关于Socket, 多线程的Overlapped操作的例子,看到它的:send/recv
就是将sendOverlapped/recvOverlapped hEvent进行CreateEvent赋值,并对其WaitFor,当正
确返回后,再用GetOverlappedResult进行得到send/recv 's的Result.好像与你有点出入。

例子在:
http://www.sockaddr.com/HTTPmt.zip
Multi-threaded HTTP server that uses blocking sockets, overlapped I/O and client threads to handle multiple simultaneous connections. (Requires WinSock 2)

还有mywyn,你对delphi中的Midas中的TSocketConnection(Client) and ScktSrvr(Server)熟不?
因为我这段正在试着写它的扩展,让它支持文件传输,但是一旦文件过大(10M以上),那么在server中
反应很慢,当然我那程序中有点问题,不过这个问题,就像是你在Select * from (一个很大的表)那个操作一样
如果record超过10M,那么结果是跟传大文件一样速度会很慢。哈哈,如果有时间,我还真想用
非阻塞来试着将它重写算了。
哦,如果你有兴趣,可以看一下我写的那个程序,不过先跟你说,Bug很多哦。
http://www.csdn.net/filebbs/read_topic.asp?id=992
 
完成例程是回调函数的意思。我用你给的这个例子解说一下
{HTTPMT.C}
nRet = WSARecv(lpReq->Socket, // Socket
&wsabuf, // WSABUF
1, // Number of buffers
&dwRecv, // Bytes received
&dwFlags, // Flags
&over, // WSAOVERLAPPED
NULL);//完成例程 // Completion function
在这个例子中,完成例程参数他赋了null,所以他用的是事件通知方式。这种方式有
缺陷(见上贴)。另外,在ListenThread函数中,仍然是一个连接一个线程的老路,
这种做法绝对要避免。这个例子给人的感觉是杀鸡用牛刀,根本没有体现重叠技术的
性能。
 
谢谢mywyn一直关注我的问题,我现在比较明白了,余下的只能靠自己了。^_^
 
后退
顶部