当前位置: 代码迷 >> 综合 >> Linux平台基于C++ socket实现TCP 网络通信
  详细解决方案

Linux平台基于C++ socket实现TCP 网络通信

热度:83   发布时间:2024-02-05 00:24:35.0

本文主要介绍在Linux平台基于C++ socket实现TCP网络通信。

0初步构思

初步的构思是在Linux平台实现一个客户端和一个服务端,首先客户端和服务端建立TCP连接,然后客户端和服务端可以互发消息。

1、通信流程

2、服务端代码

#include<iostream>
#include<conio.h> //kbhit()所在的库
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>//我这里close函数需要此头文件
#include<arpa/inet.h>
using namespace std;
int main()
{int server_sockfd;//服务端套接字int client_sockfd;//客户端套接字int len;struct sockaddr_in my_addr;//服务器网络地址struct sockaddr_in remote_addr;//客户端网络地址socklen_t sin_size;//这里linux的类型是socklen_tchar recv_buf[BUFSIZ];//数据接收缓冲区char send_buf[BUFSIZ];//数据传输缓冲区memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零my_addr.sin_family=AF_INET; //设置为IP通信my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上my_addr.sin_port=htons(8000); //服务器端口号//创建服务器端套接字--IPv4协议,面向连接通信,TCP协议if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0){cout<<"socket error";return 1;}//套接字绑定在服务器的网络地址下if(bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0){cout<<"bind error";return 1;}//监听连接请求 监听队列长度5if(listen(server_sockfd,5)<0){cout<<"listen error";return 1;}sin_size=sizeof(struct sockaddr_in);//等待客户端连接请求if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&(remote_addr),&sin_size))<0){cout<<"accept error";return 1;}//连接成功 收到地址cout<<"accept client"<<inet_ntoa(remote_addr.sin_addr)<<endl;len=send(client_sockfd,"Welcome to server",21,0);//接收客户端的数据并将其发送给客户端--recv返回接收到的字节数,send返回发送的字节数while(1){//接收客户端输入len=recv(client_sockfd,recv_buf,BUFSIZ,0);if(len > 0){recv_buf[len]='\0';cout<<"Received:"<<recv_buf<<" ,Info Length:"<<len<<endl;        	}//发送消息给客户cout<<"Enter string to send:";cin>>send_buf;if(!strcmp(send_buf, "quit")) break;len=send(client_sockfd, send_buf, strlen(send_buf), 0); }}//关闭套接字close(server_sockfd);close(client_sockfd);return 0;
}

3、客户端代码

#include<iostream>
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
using namespace std;
int main()
{int client_sockfd;int len;struct sockaddr_in remote_addr;char recv_buf[BUFSIZ];//数据接收缓冲区char send_buf[BUFSIZ];//数据传输缓冲区memset(&remote_addr, 0, sizeof(remote_addr));remote_addr.sin_family=AF_INET;//设置为IP通信remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址remote_addr.sin_port=htons(8000);//服务器端口号//创建客户端套接字 IPv4 tcpif((client_sockfd=socket(PF_INET, SOCK_STREAM, 0))<0){cout<<"socket error";return 1;}//绑定服务器网络地址if(connect(client_sockfd, (struct sockaddr*)&remote_addr, sizeof(struct sockaddr))<0){cout<<"connect error";return 1;} cout<<"connected to server"<<endl;;len=recv(client_sockfd, recv_buf, BUFSIZ, 0);//接受服务端消息recv_buf[len] = '\0';//循环的发送接受信息并打印接受信息(可以按需发送)--struct sockaddr))<0while(1){//发送消息给服务端cout<<"Enter string to send:";cin>>send_buf;if(!strcmp(send_buf, "quit")) break;len=send(client_sockfd, send_buf, strlen(send_buf), 0);//从客户端接受消息len=recv(client_sockfd,recv_buf,BUFSIZ,0);if(len > 0){recv_buf[len]='\0';cout<<"Received:"<<recv_buf<<" ,Info Length:"<<len<<endl;        	}}close(client_sockfd);return 0;
}

4、优化方向

将输入设置为无阻塞的,即可以连续接收和发送。

注:

在退出连接后,如何解除端口绑定?

1.查看800端口是否被占用:

netstat -anp | grep 8000
输出结果:tcp        4      0 127.0.0.1:41766         127.0.0.1:8000          CLOSE_WAIT  2972/./client  

由上可知8000端口已经被占用,占用进程号为2972。

2、终止该进程

kill 2972

  相关解决方案