对TCP和UDP按照书上代码实现过程 并 讲解三次握手、四次挥手过程

对于tcp的客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(sockfd != -1);

    struct sockaddr_in ser, cli;
    memset(&ser, 0, sizeof(ser));

    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = connect(sockfd, (struct sockaddr*)&ser, sizeof(ser));
    assert(res != -1);

    while(1)
    {
	printf("please input data: ");
	fflush(stdout);
	char buff[128] = {0};
	fgets(buff,128,stdin);

	buff[strlen(buff) - 1] = 0;

	if(strcmp(buff,"end") == 0)
	{
	    break;
	}

	send(sockfd,buff,strlen(buff),0);
	
	char recvbuff[128] = {0};

	recv(sockfd, buff, 127, 0);
	printf("%s\n",buff);

    }
    close(sockfd);
}

对于tcp的服务器端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(sockfd != -1);

    struct sockaddr_in ser, cli;
    memset(&ser, 0, sizeof(ser));

    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

   //绑定 命名
   //1.ip地址不对
   //2.端口号被占用或者每权限
   
    int res = bind(sockfd, (struct sockaddr*)&ser,sizeof(ser));
    assert( res != -1);

    listen(sockfd,5);
    

    while(1)
    {
	int len = sizeof(cli);
        int c = accept(sockfd, (struct sockaddr*)&cli,&len);
	
        if( c < 0)
        {
	    printf(" error\n");
	    return 0;
	}

	while(1)
	{

	    char recvbuf[128] = {0};
	    int n = recv(c, recvbuf, 127, 0);  //阻塞运行
	    if( n <= 0)
	    {
		printf("one client break\n");
		break;
	    }
	
	    printf("%d:%s\n", c, recvbuf);

	    send(c, "ok", 2, 0);
	}

	close(c);
    }
}

udp的客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    if(argc >= 3)
    {
	printf("please choose server's IP && port\n");
	exit(0);
    }

    int port = 0;
    sscanf(argv[2], "%d", &port);
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    assert(sockfd != -1);

    struct sockaddr_in ser, cli;
    memset(&ser, 0, sizeof(ser));

    ser.sin_family = AF_INET;
    ser.sin_port = htons();
    ser.sin_addr.s_addr = inet_addr(argv[1]);

    while(1)
    {
	printf("please input data: ");
	fflush(stdout);

	char buff[128] = {0};
	fgets(buff,128,stdin);

	buff[strlen(buff) - 1] = 0;

	if(strcmp(buff,"end",3) == 0)
	{
	    close(sockfd);
	    break;
	}

	sendto(sockfd,buff,strlen(buff),0,
	(struct sockaddr *)&ser,sizeof(ser));

	char recvbuff[128] = {0};
	recvfrom(sockfd, recvbuff, 127, 0, NULL,NULL);

	printf("%s\n", recvbuff);

	

	recv(sockfd, buff, 127, 0);
	printf("%s\n",buff);

    }
    close(sockfd);
}

对于udp的服务器端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    assert(sockfd != -1);

    struct sockaddr_in ser, cli;
    memset(&ser, 0, sizeof(ser));

    ser.sin_family = AF_INET;
    ser.sin_port = htons(6500);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

   //绑定 命名
   //1.ip地址不对
   //2.端口号被占用或者每权限
   
    int res = bind(sockfd, (struct sockaddr*)&ser,sizeof(ser));
    assert( res != -1);
 

    while(1)
    {
	char recvbuff[128] = {0};
	int len = sizeof(cli);
	int n = recvfrom(sockfd, recvbuff, 127, 0,(struct sockaddr*)&cli, &len);
	if( n <= 0)
	{
	    printf("recvfrom error\n");
	    continue;
	}

	printf("recvbuff: %s\n", recvbuff);

	sendto(sockfd, "ok", 2, 0,(struct sockaddr*)&cli, sizeof(cli));

    }

    close(sockfd);

}

 

TCP是面向连接 可靠的 字节流式服务

UDP是无连接的 不可靠的 数据报服务

TCP通信主要是包括三个步骤:建立TCP连接通道;传输数据;断开TCP连接通道

三次握手:

1.客户端发送SYN包到服务器端,进入SYN_SEND状态,等待服务器确认

2.服务器收到SYN包,确认客户的SYN,同时自己发送一个SYN+ACK包给客户端,此时服务器进入SYN_RECV状态

3.客户端收到SYN+ACK包之后,发送给服务器ACK确认包,此时二者同时进入连接建立状态

数据传输:

超时重传、快速重传、流量控之、拥塞控制(均是为了提供可靠的字节流服务)

四次挥手:

  1. 客户端发送一个FIN,提出断开连接的请求
  2. 服务器收到FIN包之后,对其作出响应,发送一个ACK包给对方,确认这方连接即将关闭
  3. 等服务器做好关闭准备时,服务器再反方向发送一个FIN给客户端,请求关闭连接请求
  4. 客户端对服务器所发送的请求进行确认,并发送一个ACK包
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值