tcp网络通信
一、源代码说明
freecplus是一个Linux系统下的C/C++开源框架,源代码请前往C语言技术网(www.freecplus.net)下载。
本文介绍的是freecplus框架的TCP/IP协议网络通信的函数和类。
函数和类的声明文件是freecplus/_freecplus.h。
函数和类的定义文件是freecplus/_freecplus.cpp。
示例程序位于freecplus/demo目录中。
编译规则文件是freecplus/demo/makefile。
二、概述
freecplus框架对socket通信封装如下:
CTcpClient类:socket通信的客户端类。
CTcpServer类:socket通信的服务端类。
TcpRead函数:接收socket的对端发送过来的数据。
TcpWrite函数:向socket的对端发送数据。
Readn函数:从已经准备好的socket中读取数据。
Writen函数:向已经准备好的socket中写入数据。
在阅读本文章之前,您必须熟悉TCP/IP协议和socket通信,本文是介绍的是freecplus框架中网络通信的类和函数的用法,不会介绍网络通信的基础知识。
三、通信的报文格式
freecplus框架的socket通信报文格式如下:
报文长度+报文内容
报文长度为4字节的整数,表示的是报文内容的长度,而不是整个TCP报文的长度,整个TCP报文的长度是报文内容的长度+4。
报文长度是4字节的整数,即int,是以二进制流的方式写入socket,不是ascii码。
采用CTcpClient类、CTcpServer类、TcpRead函数和TcpWrite函数进行socket通信,可以避免TCP报文粘包的问题。
四、socket通信客户端
socket通信的客户端封装在CTcpClient类中。
类的声明:
1 | // socket通信的客户端类 |
五、socket通信的服务端
socket通信的服务端封装在CTcpServer类中。
类的声明:
1 | // socket通信的服务端类 |
六、示例程序
1、客户端
示例(demo47.cpp)
1 | /* |
2、服务端
示例(demo48.cpp)
1 | /* |
3、运行程序前的准备端
我希望您已经学过计算机网络的基础知识,在运行示例程序之前,请确保您的Linux操作系统已开通防火墙。
在demo47.cpp和demo48.cpp程序中,服务端的ip地址和通信端口是写死在程序中的,请根据您的实际情况修改它们,然后重新编译。
4、运行程序
先启动demo48,然后启动demo47。
demo47的运行效果如下:
demo48的运行效果如下:
七、socket通信的函数
采用CTcpClient和CTcpServer类实现socket通信功能非常方便,但是在实际开发中,某些场景中不能只依赖这两个类,例如多程线和异步通信等场景,还必须结合以下将要介绍的几个函数一起使用。
1、TcpRead函数
接收socket的对端发送过来的数据。
函数的声明:
1 | bool TcpRead(const int sockfd,char *buffer,int *ibuflen,const int itimeout=0); |
参数说明:
sockfd:可用的socket连接。
buffer:接收数据缓冲区的地址。
ibuflen:本次成功接收数据的字节数。
itimeout:接收等待超时的时间,单位:秒,缺省值是0-无限等待。
返回值:true-成功;false-失败,失败有两种情况:1)等待超时;2)socket连接已不可用。
在CTcpClient和CTcpServer类的Read方法中调用了TcpRead函数。
2、TcpWrite函数
向socket的对端发送数据。
函数的声明:
1 | bool TcpWrite(const int sockfd,const char *buffer,const int ibuflen=0); |
参数说明:
sockfd:可用的socket连接。
buffer:待发送数据缓冲区的地址。
ibuflen:待发送数据的字节数,如果发送的是ascii字符串,ibuflen取0,如果是二进制流数据,ibuflen为二进制数据块的大小。
返回值:true-成功;false-失败,如果失败,表示socket连接已不可用。
在CTcpClient和CTcpServer类的Write方法中调用了TcpRead函数。
3、Readn函数
从已经准备好的socket中读取数据。
函数的声明:
1 | bool Readn(const int sockfd,char *buffer,const size_t n); |
sockfd:已经准备好的socket连接。
buffer:接收数据缓冲区的地址。
n:本次接收数据的字节数。
返回值:成功接收到n字节的数据后返回true,socket连接不可用返回false。
注意:
1)sockfd是已经准备好的socket连接,那什么是已经准备好的socket?在这个socket上,已经或马上有n字节的数据一定会到达。
2)成功接收到n字节的数据后返回true,如果没有n字节的数据怎么办?不会,在1)中已经说明了,一定会有n字节的数据会到达。
3)如果数据大于n字节怎么办?Readn只读取n个字节的数据,其它的数据属于其它的报文。
4)socket的对端是采用Writen方法写入的数据。
在TcpRead函数中,调用了Readn函数。
4、Writen函数
向已经准备好的socket中写入数据。
函数的声明:
1 | bool Writen(const int sockfd,const char *buffer,const size_t n); |
sockfd:已经准备好的socket连接。
buffer:待发送数据缓冲区的地址。
n:待发送数据的字节数。
返回值:成功发送完n字节的数据后返回true,socket连接不可用返回false。
在TcpWrite函数中,调用了Writen函数。
八、版权声明
C语言技术网原创文章,转载请说明文章的来源、作者和原文的链接。
来源:C语言技术网(www.freecplus.net)
作者:码农有道