TCP服务器

发布于:2023-01-21 ⋅ 阅读:(489) ⋅ 点赞:(0)

TCP是一种面向广域网的通信协议,目的是在跨越多个网络通信时,为两个通信端点之间提供一条具有下列特点的通信方式:

1、面向连接

2、可靠的(数据无丢失 、数据无失序 、数据无错误 、数据无重复到达)

3、基于字节流传输层协议

使用严格的应答机制来保证可靠性

严格的应答机制是指其建立连接时需要进行三次握手、断开连接时需要进行四次挥手操作

TCP三次握手

SYN:表示请求连接            ACK:表示应答            FIN:表示请求断开

第一次握手:client ------> server SYN = 1                 客户端发送 SYN 标志的数据包给服务器

第二次握手:server-----> client SYN = 1, ACK = 1    服务器发送 SYN+ACK标志的数据包给客户端

第三次握手:client ----> server,ACK = 1                  客户端发送 ACK 标志的数据包给服务器

如图所示:

TCP 四次挥手

第一次挥手:client -----> server FIN              客户端发送 FIN 标志的数据包给服务器

第二次挥手: server -----> client ACK              服务器发送 ACK 标志的数据包给客户端

第三次挥手: server -----> client FIN                服务器发送 FIN 标志的数据包给客户端

第四次挥手:client -----> server ACK             客户端发送 ACK 标志的数据包给服务器

注:1、每次发送数据后,都必须要应答

2、会给每个数据包编号,应答时区分

TCP服务器的设计流程

1: 建立套接字

2: 绑定ip地址与端口号

3: 建立监听队列,让套接字进入到被动监听状态

4: 接受连接,产生新的套接字

5: 数据读写(接收、发送)

#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h>	       /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
	int ret;
	int sfd,cfd;
	ssize_t recv_bytes,read_bytes;
	char buf[128] = {0};
	struct sockaddr_in src,cli;
	socklen_t len = sizeof(src);
	socklen_t addrlen = sizeof(cli);
	sfd = socket(AF_INET,SOCK_STREAM,0);//创建套接字
	if(sfd == -1)
	{
		perror("socket fail");
		return -1;
	}
	printf("sfd:%d\n",sfd);
	src.sin_family = AF_INET;
	src.sin_port = htons(atoi(argv[2]));
	src.sin_addr.s_addr = inet_addr(argv[1]);
	ret = bind(sfd,(const struct sockaddr *)&src,len);//绑定地址
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}
	ret = listen(sfd,10);//将套接字设定为被动监听状态,监听客户端的连接请求
	if(ret == -1)       //10为未决队列长度
	{
		perror("listen");
		return -1;
	}
	cfd = accept(sfd,(struct sockaddr *)&cli,&addrlen);//接收客户端连接请求,产生套接字
	if(cfd == -1)            //用于和客户端通信,通过cli保存客户端ip地址和port口号
	{
		perror("accept");
		return -1;
	}
	printf("client IP: %s PORT %d\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));
	while(1)
	{
		memset(buf,0,sizeof(buf));
		recv_bytes = recv(cfd,buf,sizeof(buf),0);//接收客户端发送的数据
		if(recv_bytes == -1)
		{
			perror("recv");
			return -1;
		}else if(recv_bytes == 0)
		{
			printf("client shutdown\n");
			break;
		}
		printf("buf:%s\n",buf);
		read_bytes = send(cfd,buf,strlen(buf),0);//返回数据
		if(read_bytes == -1)
		{
			perror("read");
			return -1;
		}
	}
	close(sfd);
	close(cfd);
	return 0;
}

本文含有隐藏内容,请 开通VIP 后查看