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

本文详述了如何在Linux环境下使用C++通过socket实现TCP通信,包括客户端和服务端的代码实现,以及讨论了通信流程和优化方向,如设置输入为无阻塞。此外,还介绍了检查和解除端口绑定的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要介绍在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_t
    char 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;
    }
    //监听连接请求 监听队列长度5
    if(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 tcp
	if((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))<0
	while(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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cchangcs

谢谢你的支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值