TCP服务器通信

来源:互联网 发布:moodle网络课程平台 编辑:程序博客网 时间:2024/06/06 09:53

TCP协议的通信流程:


单进程版本的Server.c

服务器主要用到的端口:
socket():打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应⽤用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。
bind():作用是将参数sockfd和myaddr绑定在一起,使sockfd这个⽤用于网络通讯的⽂文件描述符监听myaddr所描述的地址和端口号。
accept():典型的服务器程序可以同时服务于多个客户端,当有客户端发起连接时,服务器调用的accept()返回并接受这个连接,如果有大量的客户端发起连接而服务器来不及处理,尚未accept 的客户端就处于连接等待状态。
listen():声明sockfd处于监听状态,并且最多允许有backlog个客户端处于连接等待状态,如果接收到更多的连接请求就忽略。listen()成功返回0,失败返回-1。




client.c

客户端主要用到的端口:
由于客户端不需要固定的端口号,因此不必调用bind(),客户端的端口号由内核自动分配。
客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1

进行本地环回测试:


多进程版本:(部分代码)




多线程版本:


bind()为什么会失败?

虽然以上几个版本的服务器都能进行通信,但是都存在一个问题,服务器一旦退出,不能立即启动,也就是bind()失败。上边已经介绍了bind()的作用,将参数sockfd和myaddr绑定在一起,使sockfd这个⽤用于网络通讯的文件描述符监听myaddr所描述的地址和端口号。虽然服务端应用程序终止了,但是TCP协议层的连接并没有完全断开,因此不能监听同样的server端口。client终止时,自动关闭socket描述符,TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待两个MSL的时间后才能回到CLOSED状态,因为server先被终止,所以在TIME_WAIT期间不能再次监听同样的server端口。显然这是不合理的,这里完全断开是指conn_fd没有完全断开,而我们重新监听的是listen_fd,虽然占用同一个端口,但是IP地址不同,conn_fd 对应客户端的IP地址,listen_fd对应服务端地址。
解决方法:使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同但IP不同的多个socket描述符。所以只需在server代码中的socket()和bind()调用之间插入下面代码:

int opt = 1;setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));