socket编程
目的:使用socket编程实现一个TCP协议的客户端和服务端
环境:Ubuntu
单工通信
使用socket实现基本的单工传输,也即是服务端可以单方面发送消息给客户端,但是客户端无法发送消息给服务端。
先介绍重要的代码解析:
首先分析一下服务端的代码。
这部分代码声明了套接字,并且为套接字安排了一个“地方”。包括设置协议IPv4,具体的IP地址,这里是本机。还有端口。
这部分代码是绑定套接字。但是在绑定之前,使用了setsockopt函数,这是为了避免bind失败。我在调试的过程中,发现第一次运行服务端程序和客户端程序都完全没有问题,但是当我关掉之后再次运行,就会出现bind错误。后来我查找原因,是因为一个socket陷阱。即使连接断开,但是TCP套接字状态TIME_WAIT将保持2到4分钟。这导致端口占用,必须换一个端口。所以为了避免这种情况,我使用setsockopt允许地址重用。On=1表示允许重用,0表示不允许。
这部分代码用于监听客户端的连接请求,使用accept来建立连接,显示连接成功。
这部分代码用于向客户端发送数据。并关闭套接字。
接下来分析一下客户端的代码:
同服务端类似。声明socket并分配“地方”。
建立连接。
这部分代码主要用于接受服务端的数据,除此之外还有一个很重要的地方。就是检测连接状态。但服务端关闭之后,这边的客户端也可以立即响应,采取相应的措施。使用的是tcp_info检测。建立状态下info.tcpi_state的值是1(TCP_ESTABLISHED)表示连接成功。否则,则是断开。这一点非常有用。
结果
后来采用允许端口复用解决问题。
此时还是处于连接状态,当关闭服务端之后,显示如图4所示。
这是使用了tcp状态监测函数,在运行阶段不断进行监测。当然,还可以使用心跳法,就是每隔一段时间发送消息,若接受不到则是断开。
源代码下载:单工通信
双工传输信息
单工传输我觉得太过于简陋,至少也得是双工传输,所以在此基础上添加了双工。客户端和服务端之间可以相互通信。主要是使用了select方法。
代码分析:
先分析一下服务端的代码:
其实主要代码和上面的单工类似,这里主要介绍不同点。
这部分代码是等待连接客户端,监听到之后建立连接。
这部分内容是最重要的,使用了select函数。Select并不是阻塞函数,而是非阻塞函数,(当然,这是相对的,这可以通过设置超时来改变)。使用select的作用是可以通过返回值来监听文件描述符的变化,并且判断什么时候可以读取数据,什么时候可以写数据。这就实现了双工通信的功能。
接下来分析一下客户端的代码:
同样的,建立连接。
使用select来实现监听。现在其实服务端和客户端的地位是相对平等的。
实验结果:
两者可以互相通信。
当然,如果客户端退出,在服务端也是可以检测出来的。
源代码下载:双工通信
参考资料
socket 的位置
http://www.360doc.com/content/14/0804/15/12928831_399366221.shtml
检测连接状态
https://www.cnblogs.com/gwwdq/p/9261615.html
bind 失败
https://blog.****.net/fern_girl/article/details/73657825
bind() VS connect()
https://stackoverflow.com/questions/27014955/socket-connect-vs-bind
socket中文讲解
https://www.cnblogs.com/elve960520/articles/8379465.html
英文讲解翻译
http://www.cnblogs.com/kefeiGame/p/7246942.html
select总结
http://www.cnblogs.com/Anker/p/3265058.html
select 介绍
https://www.cnblogs.com/maowang1991/p/3567732.html
聊天室代码[非常值得一看]
http://www.cnblogs.com/diligenceday/p/6241021.html