服务端阻塞模式的Socket运行内幕(100分)

  • 主题发起人 主题发起人 masm
  • 开始时间 开始时间
M

masm

Unregistered / Unconfirmed
GUEST, unregistred user!
例如传输一个文件,每次我们传输1K字节的数据
那么,在客户端建立一个线程,在循环里依次发送1K字节直到全部发送完毕断开连接;
在服务端,数据到了,服务端控件(如Indy)将自动建立一个对应的线程,立即运行其Execute过程。问题来了:
1、如果每次接收1K数据后,保存,退出,线程销毁;第二个数据包来了,再次建立运行,接收数据,保存,退出,线程销毁...如此循环,直到整个文件传输完毕。我已经按照这个原理验证过,一切正常。
2、第一次接收数据后,在线程中建立循环,在这个线程中读取完整的文件数据并保存后才退出这个线程并销毁。如果这样做,那么第二个数据包来了,服务端控件是否还会自动建立一个对应的线程?如果不是,那么服务端是如何知道我是每一次线程运行只读取1K数据,还是线程一旦运行就读取全部数据??
 
我自己琢磨了一下,请高手不要见笑!
一个数据包进入网卡,网卡产生一个中断,让CPU进行处理(高级的网卡可能会自己处理一部分工作),CPU接管后,把数据对照各种标准协议进行分析(例如通过代理的数据包),判断该数据包是连接请求还是断开请求还是普通数据包等等,如果是连接请求,如果资源允许则建立该用户信息表并产生Connect事件,同时建立起连接(就是开辟一块内存,保存一些验证信息),如果普通数据包来了,看验证信息是否是已经建立连接的用户发来的,否则丢弃。是的话,数据拷贝至系统内存,清除网卡缓存。然后检查服务端的线程Execute是否还在运行,如果没有就建立运行;如果已经运行就忽略...
瞎猜的,呵呵。
 
我想了一下试着说一下!!
SERVER端:
有一个主线程,有联接那么新建一个线程,那么与这个服务器联接的客户端就一直通过这一个线程发送和接收!!(而不需要如果每次接收1K数据后,保存,退出,线程销毁)

按你上边的说法如果连接过多,不断的建立销毁线程对服务器的负担很重的!
 
问题是,我用每1K数据建立、销毁线程这种方式成功地传输了几百兆的文件!!而且速度和用流文件的方式一样。
你说的“有一个主线程,有联接那么新建一个线程,那么与这个服务器联接的客户端就一直通过这一个线程发送和接收!!”,连接是不能运行服务端线程的(execute不运行),数据接收才使其运行,问题是第一个数据包能激发execute,第二个包也能...如果第一个线程不释放,那么,线程数急剧增加??事实不是这样的!所以我猜测,第一个数据包激发execute后,后续的包要看execute是否还在运行,没有的话才激发。不知对不对!

 
建立线程很耗系统时间的,如果客户端并发数据量小到无所谓,如果很大的话,服务器处理不过来,会导致客户端阻塞,甚至数据丢失。
也不用每次都建立/销毁线程吧?开始建立一次,用一个while循环不断地进行接收,直到收到文件结束的标记,再销毁线程比较好。
至于一次接收的字节数,是由你的接收函数的参数(很抱歉,没用过indy,所以也不知道是哪个函数。但我想socket阻塞模式编程应该相差不大)来决定的,我通常用一个结构来定义。
但考虑到网络的复杂性,并不是每次读取/收发的字节数就是你期望的数量,所以你需要检查每次收发的字节数,并保证每个数据包的完整性。
其实我们在程序里Send/Recv数据,只是把数据包复制到了系统TCP/IP的缓冲区里,真正收发数据包的是系统(AFD.SYS)。
 
后退
顶部