注:本专栏仅面对一个对象进行编写,但是思路是一样的,并且每个部分都是按照封装思路来编写,只要创建一个自己的类,再将封装好的部分放进去就可以实现面对多对象
本专栏按照以下顺序编写
一、服务端Bind封装,开启监听
二、建立客户端,进行connect,select,send,recv封装
三、服务端Accept封装
四、服务端通过另一线程Recv客户端的消息,并做出回应
五、在Linux上实现通信
完成TCP通信
注意:由于Linux环境下和window环境下所用到的头文件和函数会有些许不一样,为了能够实现在Linux和window上的可移植性,请注意第一章节开头补充的头文件说明
Accept部分还是挺短的,也没用到什么新函数,和一些看不懂的参数之类的
在完成了第一章的Bind封装,开启监听之后就可以开始Accept封装啦
将Accept部分放到一个死循环for(;;)或while(1)中
for(;;)
{
三、服务端Accept封装
(1)再声明一个sockaddr_in caddr;
用于在accept时接收发信息的客户端的地址
sockaddr_in caddr;
socklen_t len = sizeof(caddr);
在本专栏第一篇已经解释过这个结构体,这里不再过多赘述
(2)调用accept函数
accept只是读取的TCP三次握手后的信息,三次握手已经在系统内部做完了
在对方发出connect连接请求的时候就已经完成了三次握手
int client_sock = accept(sock, (sockaddr*)&caddr, &len);
第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址
第三个参数为客户端协议地址的长度。
注意:accept返回的是一个套接字,用于独立的跟传进accept的sock客户端进行独立通信!
(3)将收到的客户端的网络地址转换成" . "
这个inet_ntoa函数也再之前篇章解释过啦
string Client_ip = inet_ntoa(caddr.sin_addr);
方便后面printf出来检查
(4)网络字节序转本地
网络字节序也再上一篇专栏解释过啦,还是讲的挺仔细的,感兴趣可以去看看呀
unsigned short Client_port = ntohs(caddr.sin_port);
(5)打印接收成功信息
printf("client ip is %s,port is %d\n", tcp.ip.c_str(), tcp.port);
注意:printf不能打印string类,要调用c_str()转成C类字符!!!
Accept部分封装完毕
四、服务端通过另一线程Recv客户端的消息,并做出回应
}//循环结束