• TCP服务端和客户端编程流程+代码详细解析(linux:c语言)


    TCP服务端和客户端的编程流程是网络编程的重点。以下内容包括编程步骤、代码实现、以及代码解析四个方面。

    目录

    1 编程步骤

    2 代码实现

    3 代码解析


    1 编程步骤

    tcp服务器与客户端的编程流程如下所示:

    左边为服务端,右边为客户端。

    我们常见的服务器客户端大多都是遵循这个步骤的。

    2 代码实现

    我们按照上述步骤来实现一个简易的服务端与客户端:

    ser.c

    # include
    # include
    # include
    # include
    # include
    # include
    # include
    # include
    int main()
    {
    	//创建套接子
    	//AF_INFT表示ipv4  SOCKET_STREAM表示传输层使用tcp协议 
    	int sockfd = socket(AF_INET,SOCK_STREAM,0);
    	assert(sockfd!=-1);
    
    	//绑定
    	struct sockaddr_in saddr,caddr;
    	memset(&saddr,0,sizeof(saddr));
    	saddr.sin_family = AF_INET;
    	saddr.sin_port = htons(6000);//1024知名  4096保留 5000之上,临时端口
    	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    	int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    	assert(res!=-1);
    
    	listen(sockfd,5);//开机
    
    	while(1)
    	{
    		int len = sizeof(caddr);
    		int c =accept(sockfd,(struct sockaddr*)&caddr,&len);
    		if(c<0)
    		{
    			continue;
    		}
    		printf("c=%d,ip=%s
    ",c,inet_ntoa(caddr.sin_addr));
    
    		char buf[128]={0};
    		int n = recv(c,buf,127,0);
    		printf("buf(%d)=%s
    ",n,buf);
    		send(c,"ok",2,0);
    
    		close(c);//待机
    	}
    
    	
    
    
    	exit(0);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    cli.c

    # include
    # include
    # include
    # include
    # include
    # include
    # include
    # include
    int main()
    {
    	//创建套接子
    	//AF_INFT表示ipv4  SOCKET_STREAM表示传输层使用tcp协议 
    	int sockfd = socket(AF_INET,SOCK_STREAM,0);
    	assert(sockfd!=-1);
    	struct sockaddr_in saddr;
    	memset(&saddr,0,sizeof(saddr));
    	saddr.sin_family = AF_INET;
    	saddr.sin_port = htons(6000);
    	saddr.sin_addr.s_addr =inet_addr("127.0.0.1");
    	int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    	assert(res!=-1);
    	
    	printf("input:
    ");
    	char buf[128]= {0};
    	fgets(buf,128,stdin);
    	send(sockfd,buf,strlen(buf),0);
    	memset(buf,0,128);
    	recv(sockfd,buf,127,0);
    	printf("buf=%s
    ",buf);
    	close(sockfd);
    	
    
    	exit(0);
    
    }	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    程序运行结果如下图所示:

    3 代码解析

    从下面几个问题出发,对代码进行解析:

    • 服务端中listen(sockfd,5)函数的第二个参数5代表什么意思?

    首先,listen在套接字函数中表示让一个套接字处于监听到来的连接请求的状态,那么第二个参数的含义为完成三次握手建立连接的队列的长度,5就代表在等待服务器的客户端

    • 三次握手和四次挥手分别发生在什么时候

    当客户端执行connect函数的时候,开始进行三次握手。当某一端close的时候,开始四次挥手。当两端同时close的时候,四次挥手会演变为3次。

    • sockaddr_in与sockaddr结构体

    sockaddr如下:

    struct sockaddr {
    unsigned short sa_family;     /* address family, AF_xxx */
    char sa_data[14];                 /* 14 bytes of protocol address */
    };
    
    • 1
    • 2
    • 3
    • 4

    sa_family是地址家族,sa_data是一个14字节的协议地址。

    sockaddr_in如下:

    struct sockaddr_in {
    short int sin_family;            /* Address family */
    unsigned short int sin_port;       /* Port number */
    struct in_addr sin_addr;              /* Internet address */u
    nsigned char sin_zero[8];         /* Same size as struct sockaddr */
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在上述代码中我们可以发现,sockaddr和sockaddr_in可以相互转换,这是因为sockaddr是通用的套接字地址,而sockaddr_in是网络环境下的套接字地址,两个结构体的长度一样。sockaddr_in结构体中的元素sin_zero就是为了让sockaddr与sockaddr_in这两个结构体保持大小相同而预留的空字节。

  • 相关阅读:
    基于BP神经网络的含水率预测模型matlab仿真
    Reactor 第十二篇 WebFlux集成PostgreSQL
    STM32的寄存器操作
    【性能测试入门必看】性能测试理论知识
    操作系统实践课程结课报告
    案例部署——GlusterFS分布式文件系统群集
    数据结构与算法【Java】03---栈
    sql语句中查重复数据
    CSS自定义属性与前端页面的主题切换
    本地生活服务平台哪家强,怎么申请成为服务商?
  • 原文地址:https://blog.csdn.net/sebeefe/article/details/126516690