在Linux中利用C语言构建TCP网络通信实现服务器和客户端的通信

我们都知道,TCP通信是面向对象,可靠的连接服务,故TCP通信节点在软件设计中被广泛应用,因此这里实现构建一个简单的TCP通信节点demo

  • 软件环境: deepin 5.11

1.服务端构建

1)socket() – 创建通信套接字

	//1.创建套接字 --- socket()
	/*
	int socket(int domain, int type, int protocol);
	参数: domain --- AF_INET  地址族
		  type   --- 套接字类型 
		  SOCK_STREAM(流式套接字)
		  protocol --- 0
	*/
	
	int sockfd = socket(AF_INET,SOCK_STREAM,0);		//返回值0为成功,-1为失败
	if(sockfd == -1)
	{
		perror("socket");			//打印错误输出
		return -1;	 
	}
	printf("socket excute successful!\n");

2)bind() – 绑定套接字

	//2绑定套接字 --- bind()
	/*
	int bind(int sockfd, const struct sockaddr *addr,
                socklen_t addrlen);
	参数: sockfd  ——-- 套接字文件描述符
		  addr   ---  通用地址结构
		  addrlen --- 地址的长度
	*/		

	struct sockaddr_in myaddr;                //IPV4地址结构体
	memset(&myaddr, 0, sizeof(myaddr));
	myaddr.sin_family = AF_INET;              
	myaddr.sin_port = htons(8888);           //自定义设置端口号   5001~65535
	myaddr.sin_addr.s_addr = inet_addr("192.168.3.121");  //自定义设置为此服务器所在的IP地址
	
	if (bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)) == -1)						//0成功 -1失败
    {
		perror("bind");
		return -1;
	}
	printf("bind success!\n"); 

3)listen() – 设置监听套接字

	//3设置监听套接字 --- listen()
	/*
	int listen(int sockfd, int backlog);
	参数: sockfd --- 套接字文件描述符
	       backlog -- 监听队列的长度
	*/ 

	if(listen(sockfd,5) == -1)
	{
		perror("listen");
		return -1;	//返回现在执行的函数(结束函数) 
	}
	printf("listen successful!\n"); 

4) accept() – 接受客户端的连接

	//4等待客户端的连接 --- accept()
    /*
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
		参数: sockfd --- 套接字文件描述符
                       第二/三个参数设置为NULL
    */

	int connfd = accept(sockfd,NULL,NULL);
	if(connfd == -1)
	{
		perror("accpet!");
		return -1;	//返回现在执行的函数(结束函	
	}
	printf("accpet success!\n");

5) read() – 服务端收数据

	//5收来自客户端的数据 --- read()
	/*
	ssize_t read(int fd, void *buf, size_t count);
	 参数:fd --- 文件描述符
		  buf --- 缓冲区首地址
		  count --- 想要读取的字节数
	返回值: 
			成功: >0  --- 成功读取的字节数
				  =0  --- 读到文件末尾
			失败: -1  --- 设置errno
	*/

	char buf[1024];
	while(1)
	{
		memset(buf,0,sizeof(buf));		//将 buf空间中的1024内容清空 
		 
		read(connefd,buf,sizeof(buf));	//表示把buf中的呢熊读入 
		int ret = read(connefd,buf,sizeof(buf));
		if(ret == -1)			//读取失败 
		{	
			perror("read!");
			break;
		}
		else if(ret == 0)		//写端口关闭 
		{
			printf("client close\n")
		}
		else				   //成功接收
		{
			printf("recv : %s\n");
		 } 
		 if (0 == strcmp(buf, "exit"))	//判断是否退出
			break;
		
		//添加客户端和服务端信息交互
		printf("send: ");
		fgets(buf,1024,stdin);
		ret = write(connfd, buf, sizeof(buf));
		if (ret == -1) {
			perror("write");
			break;
		}
		if (strcnmp(buf, "exit",4) == 0)
			break;
	}

6) close() – 关闭套接字

	//6关闭套接字 --- close()
	close(connfd);			//关闭连接
	close(sockfd);			//关闭文件描述符

2.客户端构建

客户端的构建原理方式,步骤和服务端大似相同

1)socket() – 创建套接字

	//1.创建套接字
	int sockfd = socket(AF_INET,SOCK_STREAM,0);		
	if(sockfd == -1)
	{
		perror("socket");
		return -1;	
	}
	printf("socket excute successful!\n");

2)connect() – 主动连接服务器

原理步骤和绑定服务器设置相同

	//2.连接服务器
	struct sockaddr_in myaddr;                //IPV4地址结构体
	memset(&myaddr, 0, sizeof(myaddr));
	srvaddr.sin_family = AF_INET;              
	srvaddr.sin_port = htons(8888);           //端口号   5001~65535
	srvaddr.sin_addr.s_addr = inet_addr("192.168.3.121");  //设置IP地址
	
	if (-1 == connect(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr))) {
		perror("bind");
		return -1;
	}
	printf("bind success!\n"); 

3)write() – 发数据

	//3.发数据
	char buf[1024];
	int ret;
	while(1)	//循环从键盘输入串 
	{
		printf("send : ");
		fget(buf,1024,stdin);		//输入字符串并存入buf 
		ret = write(sockfd,buf,sizeof(buf));
		if(ret == -1)
		{
			perror("write");
			break;
		}
		if (strncmp(buf, "exit",4) == 0)	
			break;

		ret = read(sockfd, buf, sizeof(buf));
		if (ret == -1) {
			perror("read");
			break;
		}else if (0 == ret) {
			printf("server close!\n");
			break;
		}
		printf("recv: %s\n", buf);
		if (strcnmp(buf,"exit",4 ) == 0)
			break;
	}

4)close() – 关闭套接字

//4.关闭
close(sockfd);

3.效果展示

在这里插入图片描述

4.全部代码

  • 服务端
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
			
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>


int main()
{
	//1创建套接字
	//man socket查看手册 
	int sockfd = socket(AF_INET,SOCK_STREAM,0);		 
	if(sockfd == -1)
	{
		perror("socket");
		return -1;	
	}
	printf("socket excute successful!\n"); 
	
	//2绑定套接字
	struct sockaddr_in myaddr;                //IPV4地址结构体
	memset(&myaddr, 0, sizeof(myaddr));
	myaddr.sin_family = AF_INET;              
	myaddr.sin_port = htons(8888);           //端口号   5001~65535
	myaddr.sin_addr.s_addr = inet_addr("192.168.232.130");  //设置IP地址
	
	if (-1 == bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr))) {
		perror("bind");	
		return -1;
	}
	printf("bind success!\n"); 
	
	//3设置监听套接字
	if(listen(sockfd,5) == -1)
	{
		perror("listen");
		return -1;	//返回现在执行的函数(结束函数) 
	}
	printf("listen successful!\n"); 
	
	//4接受客户端的连接。并生成新的通信套接字
	//accpet() 
	int connfd = accept(sockfd,NULL,NULL);			//定义套接字
	if(connfd == -1)
	{
		perror("accpet!");
		return -1;	//返回现在执行的函数(结束函	
	}
	printf("accpet success!\n");
	
	//5收数据
	char buf[1024];
	while(1)
	{
		memset(buf,0,sizeof(buf));		//将 buf空间中的1024内容清空 
		int ret = read(connfd,buf,sizeof(buf));
		if(ret == -1)			//读取失败 
		{	
			perror("read!");
			break;
		}
		else if(ret == 0)		//写端口关闭 
		{
			printf("client close\n");
		}
		else
		{
			printf("recv : %s\n");
		 } 
		 if (0 == strncmp(buf, "exit",4))	//判断是否退出
			break;
		
		//添加客户端和服务端信息交互
		printf("send: ");
		fgets(buf,1024,stdin);
		ret = write(connfd, buf, sizeof(buf));
		if (ret == -1) {
			perror("write");
			break;
		}
		if (strcnmp(buf, "exit",4) == 0)
			break;
	}
	
	
	//6关闭套接字 
	close(connfd);
	close(sockfd);
	 
	
	return 0;
 } 
  • 客户端
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
			
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

int main()
{
	//1.创建套接字
	//socket();
	int sockfd = socket(AF_INET,SOCK_STREAM,0);		
	if(sockfd == -1)
	{
		perror("socket");
		return -1;	//返回现在执行的函数(结束函数) 
	}
	printf("socket excute successful!\n");
	
	
	//2. 主动连接服务器
	//connect();
	struct sockaddr_in srvaddr;                //IPV4地址结构体
	memset(&srvaddr, 0, sizeof(srvaddr));
	srvaddr.sin_family = AF_INET;              
	srvaddr.sin_port = htons(8888);           //端口号   5001~65535
	srvaddr.sin_addr.s_addr = inet_addr("192.168.232.130");  //链接服务器的IP地址
	
	if (-1 == connect(sockfd, (struct sockaddr*)&srvaddr, sizeof(srvaddr))) {
		perror("bind");
		return -1;
	}
	printf("bind success!\n"); 
	
	
	//3.发数据
	//write()
	char buf[1024];
	int ret;
	while (1) {
		printf("send: ");
		fgets(buf,1024,stdin);   
		ret = write(sockfd, buf, sizeof(buf));
		if (-1 == ret) {
			perror("write");
			break;
		}
		if (strncmp(buf, "exit",4) == 0)		//判断是否退出
			break;

		ret = read(sockfd, buf, sizeof(buf));
		if (ret == -1) {
			perror("read");
			break;
		}else if (0 == ret) {
			printf("server close!\n");
			break;
		}
		printf("recv: %s\n", buf);
		if (strncmp(buf,"exit",4) == 0)
			break;
	}
	
	
	//4.关闭套接字
	close(sockfd); 
	
	return 0;
}
发布了43 篇原创文章 · 获赞 7 · 访问量 9030

猜你喜欢

转载自blog.csdn.net/qq_41488943/article/details/103951321