TCP套接字编写,多进程多线程版本 Linux网络通信( 六 )

INADDR_ANY,具体代码如下:
bool TcpServerInit(){// 绑定struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr = INADDR_ANY;if (bind(_listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){cout << "bind fail" << endl;return false;}cout << "bind success" << endl;}将套接字设置为监听状态这里就需要用的listen这个接口,让套接字处于监听状态,然后可以去监听连接的到来代码也很简单,具体如下:
bool TcpServerInit(){// 将套接字设置为监听状态if (listen(_listen_sock, BACK_LOG) < 0){cout << "listen fail" << endl;return false;}cout << "listen success" << endl;}循环获取连接听套接字通过accept获取连接,一次获取连接失败不要直接将服务端关闭,而是重新去获取连接就好,因为获取一个连接失败而直接关闭服务端,带来的损失是很大的,所以只需要重新获取连接即可,返回的用于通信套接字记录下来,进行通信,然后可以用多种方式为各种连接连接提供服务,具体服务方式后面细说,先看获取连接的一部分代码:
void loop(){struct sockaddr_in peer;// 获取远端端口号和ip信息socklen_t len = sizeof(peer);while (1){// 获取链接// sock 是进行通信的一个套接字_listen_sock 是进行监听获取链接的一个套接字int sock = accept(_listen_sock, (struct sockaddr*)&peer, &len);if (sock < 0){cout << "accept fail, continue accept" << endl;continue;}// 提供服务 service 后面介绍}}客户端整体框架和服务端一样,封装一个类描述,类成员有服务端ip、服务端绑定的端口号以及自身套接字,代码如下:
【TCP套接字编写,多进程多线程版本 Linux网络通信】class TcpClient{public:TcpClient(string ip, int port):_server_ip(ip),_server_port(port),_sock(-1){}~TcpClient(){if (_sock >= 0) close(_sock);}private:string _server_ip;int _server_port;int _sock;};客户端初始化客户端的初始化只需要创建套接字即可,不需要绑定端口号,发起连接请求的时候,会自动给客户端分配一个端口号 。创建套接字和服务端是一样的,代码如下:
bool TcpClientInit(){// 创建套接字_sock = socket(AF_INET, SOCK_STREAM, 0);if (_sock < 0){cout << "socket creat fail" << endl;return false;}cout << "socket creat succes, sock: " << _sock << endl;return true;}客户端启动发起连接请求使用connect函数,想服务端发起连接请求,注意,调用这个函数之前,需要先填充好服务端的信息,有协议家族、端口号和IP,请求连接失败直接退出进程,重新启动进程即可,连接成功之后就可以像服务端发起各自的服务请求(后面介绍),代码如下:
void TcpClientStart(){// 连接服务器struct sockaddr_in peer;peer.sin_family = AF_INET;peer.sin_port = htons(_server_port);peer.sin_addr.s_addr = inet_addr(_server_ip.c_str());if (connect(_sock, (struct sockaddr*)&peer, sizeof(peer)) < 0){// 连接失败cerr << "connect fail" <<endl;exit(-1);}cout << "connect success" << endl;Request();// 下面介绍}发起服务请求请求很简单,只需要让用户输入字符串请求,然后将请求通过write(send也可以)发送过去,然后创建一个缓冲区,通过read(recv也可以)读取服务端的响应,这里需要着重介绍一下read的返回值

  1. 大于0:实际读取的字节数
  2. 等于0:读到了文件末尾,说明对端关闭,用在服务端就是客户端关闭,用在客户端就是服务端关闭了,客户端可以直接退出
  3. 小于0:说明读取失败

    经验总结扩展阅读