• Linux 12:TCP编程



    1. TCP编程流程

    TCP提供的是面向连接的、可靠的、字节流服务。TCP的服务器端和客户端编程流程如下:
    在这里插入图片描述
    connect()方法一般由客户端程序执行,需要指定连接的服务器端的IP地址和端口。该方法执行后,会进行三次握手,建立连接。
    在这里插入图片描述
    在这里插入图片描述

    1.1 TCP建立连接的三次握手过程图

    三次握手发生在客户端执行connect()的时候,该方法返回成功,则说明三次握手已经建立。
    在这里插入图片描述

    1.2 TCP连接断开的四次挥手过程图

    四次挥手发绳子客户端或服务端执行close()关闭连接的时候,示例图如下:
    在这里插入图片描述

    1.3 TCP字节流式服务特点

    x

    2. TCP代码(循环输入和接收)

    ser.c

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<unistd.h>
      4 #include<stdlib.h>
      5 #include<sys/socket.h>
      6 #include<arpa/inet.h>
      7 #include<netinet/in.h>
      8 #include<pthread.h>
      9 
     10 int socket_init();
     11 void *fun(void*arg);
     12 int main()
     13 {
     14     int sockfd=socket_init();
     15     if(sockfd==-1)
     16     {
     17         exit(1);
     18     }
     19     while(1)
     20     {
     21         struct sockaddr_in caddr;
     22         int len=sizeof(caddr);
     23         int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
     24         if(c<0)
     25         {
     26             continue;
     27         }
     28         printf("accept c=%d,ip=%s,port=%d\n",c,inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
     29         pthread_t id;//创建线程
     30         pthread_create(&id,NULL,fun,(void*)c);
     31     }
     32 }
     33 void* fun(void*arg)
     34 {
     35     int c=(int)arg;
     36     while(1)
     37     {
     38         char buff[18]={0};
     39         int n=recv(c,buff,127,0);//接收数据,无数据阻塞
     40         if(n==0)
     41         {
     42             break;
     43         }
     44         printf("recv(%d)=%s\n",c,buff);
     45         send(c,"ok",2,0);
     46     }
     47     printf("close\n");
     48     close(c);
     49 }
     50 
     51 int socket_init()
     52 {
     53     int sockfd=socket(AF_INET,SOCK_STREAM,0);
     54     if(sockfd==-1)
     55     {
     56         printf("socket err\n");
     57         return -1;
     58     }
     59 
     60     struct sockaddr_in saddr,caddr;//saddr自己使用端口,caddr对方使用端口
     61     memset(&saddr,0,sizeof(saddr));
     62     saddr.sin_family=AF_INET;
     63     saddr.sin_port=htons(6000);
     64     saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
     65 
     66     int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//给套接字设置绑定端口
     67     if(res==-1)
     68     {
     69         printf("bind err\n");
     70         return -1;
     71     }
     72 
     73     res=listen(sockfd,5);
     74     if(res==-1)
     75     {
     76         printf("listen err\n");
     77         return -1;
     78     }
     79     return sockfd;
     80 }
    
    
    • 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
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    lic.c

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<unistd.h>
      4 #include<stdlib.h>
      5 #include<sys/socket.h>
      6 #include<arpa/inet.h>
      7 #include<netinet/in.h>
      8 #include<pthread.h>
      9 
     10 int main()
     11 {
     12     int sockfd=socket(AF_INET,SOCK_STREAM,0);
     13     if(sockfd==-1)
     14     {
     15         printf("socket err\n");
     16         exit(1);
     17     }
     18 
     19     struct sockaddr_in saddr;
     20     memset(&saddr,0,sizeof(saddr));
     21     saddr.sin_family=AF_INET;
     22     saddr.sin_port=htons(6000);
     23     saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
     24 
     25     //三次握手,connect返回成功,则三次握手完成
     26     int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
     27     if(res==-1)
     28     {
     29         printf("connect err\n");
     30         exit(1);
     31     }
     32     while(1)
     33     {
     34         printf("input\n");
     35         char buff[128]={0};
     36         fgets(buff,128,stdin);
     37         if(strncmp(buff,"end",3)==0)
     38         {
     39             break;
     40         }
     41         send(sockfd,buff,strlen(buff)-1,0);
     42         memset(buff,0,128);
     43         recv(sockfd,buff,127,0);
     44         printf("buff=%s\n",buff);
     45     }
     46     close(sockfd);
     47 }       
    
    • 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

    运行结果
    在这里插入图片描述
    netstat -natp
    在这里插入图片描述
    从键盘输入的数据先存入缓冲区,等到recv开始执行时候,才开始接收数据
    在这里插入图片描述
    理论上应该输出5个ok,但是由于时间原因,只接收一个,其他4个存入缓冲区,下一次执行recv时候才会输出

    tcp代码图解
    在这里插入图片描述


  • 相关阅读:
    论文阅读——Towards Adversarially Robust Object Detection
    webpack打包基础
    Prompt提示词——什么是CRISPE框架?QCIPSPE框架?
    亚商投资顾问 早餐FM/1121 2022年卡塔尔世界杯开幕
    Cisco简单配置(十八)—OSPF
    游戏开发30课 cocoscreator骨骼贴图布局设置
    3D WEB引擎HOOPS Commuicator助力Naval Architect Jumpstart快速启动船舶信息建模平台开发
    品牌线上控价,如何平台投诉
    Py之PyGTK:PyGTK的简介、安装、使用方法之详细攻略
    第八章 互联网上的音频视频服务 | 计算机网络(谢希仁 第八版)
  • 原文地址:https://blog.csdn.net/qq_48580892/article/details/126138909