网络多线程
来源:互联网 发布:bluehost linux 编辑:程序博客网 时间:2024/05/10 14:35
转自:http://blog.csdn.net/frank_jb/article/details/52037875
客户端:发送连接请求;一旦连接建立,将用户输入的信息发送给服务器;输入end,客户端程序退出
服务器端:建立监听端口;接收连接请求;为每个请求创建一个线程,接收客户端的信息并打印。
服务器端程序:
客户端:
send函数
ssize_t send(int socket, const void *buffer, size_t length, int flags);
不论是客户端还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。
参数:
- 第一个参数指定发送端套接字描述符;
- 第二个参数指明一个存放应用程序要发送数据的缓冲区;
- 第三个参数指明实际要发送的数据的字节数;
- 第四个参数用于改变函数的行为。
- 0:与write()无异,一般置0
- MSG_DONTROUTE:告诉内核,目标主机在本地网络,不用查路由表
- MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式
- MSG_OOB:指明发送的是带外信息
这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余空间大小send就仅仅把buf中的数据 copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。
如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。
注意:
- send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回SOCKET_ERROR)
- 在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
recv函数
ssize_t recv(int socket, void *buffer, size_t length, int flags);
不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。
- 第一个参数指定接收端套接字描述符;
- 第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
- 第三个参数指明buf的长度;
- 第四个参数用于改变函数的行为。
- 0:与read()相同,一般置0
- MSG_DONTWAIT:将单个I/O操作设置为非阻塞模式
- MSG_OOB:指明发送的是带外信息;在网络上有两种类型的数据包,正常包和带外包。带外包可以通过检验一个TCP/IP包头的一个特定标志来决定。
- MSG_PEEK: 可以查看可读的信息,在接收数据后不会将这些数据丢失;从输入数据中取数。数据拷入缓冲区,但不从输入队列中移走。函数返回当前准备接收的字节数。
- MSG_WAITALL:通知内核直到读到请求的数据字节数时,才返回。
这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR;如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv则去检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
注意:
- 在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。这与send函数一样,我们可以捕获该信号,在程序退出前做一些我们需要的处理。
根据上面的说明理解下面一段话:
发送方与接收方没有定制协议的情况下,接收方不可能知道发送方是否已经发送完毕,如果想要在这种情况下实现接收方接收发送方多次send()数据可以在recv时加个参数,让它只是看看有没有数据到达,recv最后那个参数设为MSG_OOB就可以,当发现有数据到时,你先Sleep一下,至于多长时间就要看实际情况,一般几十个毫秒就绝对够了,然后,你再recv一下,这次最后那个参数为MSG_WAITALL就可以,这样就一次性接收完毕
backlog参数
int listen(int socket, int backlog);
listen函数仅由TCP服务器调用,它做两件事情:
1、当socket函数创建一个套接口时,它被假设为一个主动套装口,也就是说,它是一个将调用connet发起连接的客户套接口。listen函数把一个未连接的套接口转换成一个被动套接口,指示内核应接受指向该套接口的连接请求。根据TCP状态转换图,调用listen导致套接口从CLOSED状态转换到LISTEN状态。
2、backlog其实是一个连接队列,以下是backlog队列大小公式。backlog队列总和=未完成三次握手队列 + 已经完成三次握手队列以上参数解释说明如下:
未完成三次握手队列:服务器处于listen状态时收到客户端syn 报文(connect)时放入未完成队列中。
已经完成三次握手队列:三次握手的第二个状态即服务器syn+ ack响应client后,到第三个状态ack报文到达前(客户端对服务器syn的ack)一直保留在未完成连接队列中,如果三次握手完成,该条目将从未完成连接队列搬到已完成连接队列尾部.
backlog参数设置既可以在linux内核参数设置(修改文件/etc/sysctl相关参数),也可以在socket系统调用listen函数时设置(第二个参数),这二者区别是,前者为全局性的,影响所有socket,后者为局部性的,影响当前socket。
- 多线程网络
- 多线程网络
- 网络&&多线程
- 网络多线程
- 多线程 网络
- 多线程+网络
- 网络多线程
- 多线程网络编程
- 多线程,网络聊天软件;
- 网络多线程断点下载
- 多线程网络通信
- 网络多线程断点下载
- 多线程网络模块
- 网络多线程断点下载
- 多线程的网络通信
- 多线程网络爬虫
- 多线程和网络编程
- java网络编程、多线程
- 拒绝赚“快钱”,平衡车企业应将“极致”进行到底
- 腾讯手机管家6.0 开启安全软件功能定制时代
- 每日产品辣评:LG奇葩新机发布,篡位新旗舰
- Jfinal学习日志第二章_JFinalConfig(详细图解)
- 最小生成树0.2
- 网络多线程
- 中共六大政治局
- 百度地图之开发环境配置
- 移动广告行业众生相之有米SDK事件背后的思考
- 每日产品辣评:小米Note耍猴术再次上演,55寸小米电视3发布
- JSTL核心标签库
- 怪我咯?手机已卡死还没告诉你用KingRoot
- 平衡车究竟应该坐着还是站着?
- 黑客们如何办Party?玩转GeekPwn嘉年华