TCP概念+模拟tcp服务器及客户端
目录
一、TCP基本概念
二、ser服务器代码
三、cil客户端代码
一、TCP基本概念
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层协议。以下是TCP的一些基本概念:
-
面向连接:在数据传输之前,TCP在发送方和接收方之间建立一个连接。数据传输完成后,连接被释放。
-
可靠性:TCP提供可靠的数据传输,确保数据按照正确的顺序到达目的地,并且可以检测和纠正传输过程中出现的错误。
-
流控制:TCP使用滑动窗口协议进行流量控制,以确保发送端和接收端之间的数据传输速率合理,不会发生数据丢失或超负荷的情况。
-
拥塞控制:TCP通过控制数据包的发送速率来避免网络拥塞,以确保网络的稳定性和流畅性。
-
分段和重组:TCP在传输数据时会将数据分成较小的数据段进行传输,接收方收到数据后会重新组装成完整的数据。
-
端到端通信:TCP是端到端通信协议,意味着通信双方直接进行数据传输,而不需要经过中间设备的处理。
服务端:
1. socket():创建一个新的套接字。
2. bind(ip+port):将套接字绑定到指定的IP地址和端口号上,以便监听来自该地址和端口的连接请求。
3. listen():使套接字进入监听状态,等待客户端的连接请求。
4. accept():接受客户端的连接请求,建立连接。
5. recv():接收来自客户端的数据。
6. send():向客户端发送数据。
7. close():关闭套接字,结束通信。客户端:
1. socket():创建一个新的套接字。
2. connect(ip+port):向服务端的指定IP地址和端口号发起连接请求。
3. send():向服务端发送数据。
4. recv():接收来自服务端的数据。
5. close():关闭套接字,结束通信。
二、ser服务器代码
TCP服务器程序,用于接受客户端的连接请求,并与客户端进行数据交换 。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>int main()
{//创建套接字(打开文件,文件描述符) 套接字可以通过网络收发数据int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){exit(1);}struct sockaddr_in saddr,caddr;//服务器的ip端口memset(&saddr,0,sizeof(saddr));//清空saddr.sin_family=AF_INET;//填充saddr.sin_port=htons(6000);//制定端口号为6000 小于1024是知名端口,1024~4096是保留的端口,4096以上是临时端口saddr.sin_addr.s_addr=inet_addr("127.0.0.1");//指定ip+端口int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//绑定,指定应用程序使用的ip及端口if(res==-1){printf("bind err\n");exit(1);}res=listen(sockfd,5);if(res==-1){exit(1);}while(1){int len=sizeof(caddr);//accept接受连接,如果没人连接,则阻塞int c=accept(sockfd,(struct sockaddr*)&caddr,&len);if(c<0){break;}printf("accept c=%d\n",c);pid_t pid=fork();if(pid==0){while(1){char buff[128]={0};int n=recv(c,buff,127,0);//接受连接,接收数据,会阻塞,也可以换成read()if(n<=0){break;}printf("recv:%s\n",buff);send(c,"ok",2,0);//发送数据,也可以换成write()}printf("client close\n");close(c);exit(0);}close(c);}
}
导入头文件:程序中导入了一些标准的头文件,包括stdio.h、stdlib.h、unistd.h、string.h、sys/socket.h、netinet/in.h、arpa/inet.h。
创建套接字:使用socket函数创建一个套接字,同样指定协议族(AF_INET,表示IPv4)、套接字类型(SOCK_STREAM,表示TCP流套接字)和协议参数(0)。
设置服务器地址:定义了两个结构体变量saddr和caddr,分别表示服务器和客户端地址。初始化saddr,并指定服务器的IP地址为"127.0.0.1",端口号为6000。
绑定地址:使用bind函数将套接字和服务器地址绑定在一起,指定服务器应用程序使用的IP地址和端口号。
监听连接:使用listen函数监听连接请求,指定最大连接数为5。
接受连接:通过accept函数接受客户端的连接请求。如果有客户端连接,则创建一个新的套接字描述符c,并接受连接。
多进程处理:在子进程中处理客户端的数据通信。在处理数据的循环中,接收客户端发送的数据,如果接收到数据则打印并发送"ok"回复客户端。如果接收到的数据长度小于等于0,表示客户端关闭连接,则跳出处理数据的循环,关闭客户端的套接字描述符c。
多进程处理:在父进程中关闭已接受的客户端连接。
三、cil客户端代码
客户端程序,用于连接到服务器并进行数据交换。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>int main()
{//创建套接字int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd==-1){exit(1);}struct sockaddr_in saddr;//指定服务器的ip和端口portmemset(&saddr,0,sizeof(saddr));saddr.sin_family=AF_INET;saddr.sin_port=htons(6000);//htons 转为网络字节序列 大端saddr.sin_addr.s_addr=inet_addr("127.0.0.1");int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if(res==-1){printf("connect err\n");exit(1);}char buff[128]={0};printf("input:\n");fgets(buff,128,stdin);send(sockfd,buff,strlen(buff)-1,0);//可以用writememset(buff,0,sizeof(buff));recv(sockfd,buff,127,0);printf("buff=%s\n",buff);close(sockfd);exit(0);
}
导入头文件:程序中导入了一些标准的头文件,包括stdio.h、stdlib.h、unistd.h、string.h、sys/socket.h、netinet/in.h、arpa/inet.h。
创建套接字:使用socket函数创建一个套接字,同样指定协议族(AF_INET,表示IPv4)、套接字类型(SOCK_STREAM,表示TCP流套接字)和协议参数(0)。
设置服务器地址:定义了一个结构体变量saddr,表示服务器地址。初始化saddr,并指定服务器的IP地址为"127.0.0.1",端口号为6000。
连接服务器:使用connect函数连接服务器,将套接字和服务器地址绑定在一起,连接到指定的服务器IP和端口。
发送和接收数据:提示用户输入数据,通过fgets函数读取用户输入的数据到缓冲区buff中。然后使用send函数将数据发送给服务器,发送的数据长度为输入长度减去换行符。接收服务器返回的数据,使用recv函数将数据读取到buff中。
打印数据:将接收到的数据打印输出。
关闭连接:使用close函数关闭套接字,结束客户端程序。
运行结果: