首页 > 其他分享 >TCP的通信流程和socket套接字完成服务端和客户端通信

TCP的通信流程和socket套接字完成服务端和客户端通信

时间:2023-11-04 11:56:25浏览次数:33  
标签:addr int 通信 TCP socket sizeof include buf 客户端

一、TCP是一个面向连接的安全的流式传输协议,这个协议是传输层协议。

  面向连接:是一个双向连接,通过三次握手建立连接,通过四次挥手断开连接。

  安全:tcp通信的过程中,会对发送的每一数据包都会进行校验,如果发现数据丢失,会自动重传。

  流式传输:发送端和接受端处理数据的速度,数据的量都可以不一致。

二、服务器端通信流程

    1.创建用于监听的套接字,这个套接字是一个文件描述符

1     int lfd = socket();  

  `  2.将得到的监听的文件描述符和本地 的ip端口进行绑定

1    bind();

    3. 设置监听(成功之后开始监听,监听的是客户端的连接)

1    listen();

    4.等待并接受客户端的连接请求,建立新的连接,会得到一个新的文件描述符(通信用的),没有新连接请求就阻塞

1    int cfd = accept();

    5.通信,读写操作默认都是阻塞的

1 //接受数据
2 read(); //recv();
3 
4 //发送数据
5 write(); //send();

    6.断开连接,关闭套接字

close();

    基于tcp的服务端通信代码

 1 //server.c
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 #include <string.h>
 6 #include <arpa/inet.h>
 7 
 8 int main()
 9 {
10     //1.建立监听的套接字
11     int lfd = socket(AF_INET, SOCK_STREAM, 0);
12     if (lfd == -1)
13     {
14         perror("socket");
15         exit(0);
16     }
17     
18     //设置端口复用,防止占用服务器后断开后还占用这端口,要等
19     int opt = 1;
20     setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
21     struct sockaddr_in addr;
22     
23     //2.将socket()返回值和本地的ip、端口绑定到一起
24     addr.sin_family = AF_INET;
25     addr.sin_port = htons(10000);
26     addr.sin_addr.s_addr = htonl(INADDR_ANY);
27     //INADDR_ANY代表本机的所有ip,假设有三个网卡就有三个IP地址
28     //这个宏可以代表任意一个IP地址
29     //这个宏一般用于本地的绑定操作。
30     //inet_pton(AF_INET, "192.168.0.23", &addr.sin_addr.s_addr);//绑定具体的ip
31     int ret = bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
32     if (ret == -1)
33     {
34         perror("bind");
35         exit(0);
36     }
37 
38     //3.设置监听
39     ret = listen(lfd, 128);
40     if (ret == -1)
41     {
42         perror("listen");
43         exit(0);
44     }
45 
46     //阻塞等待并接受客户端连接
47     struct sockaddr_in  cliaddr;
48     socklen_t clilen = sizeof(cliaddr);
49     int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &clilen);
50     //int cfd = accept()
51     if (cfd == -1)
52     {
53         perror("accept");
54         exit(0);
55     }
56 
57     //打印客户端的地址信息
58     char ip[24] = { 0 };
59     printf("客户端的IP地址:%s,端口:%d\n",
60         inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, ip, sizeof(ip)),
61         ntohs(cliaddr.sin_port));
62 
63     //5.和客户端通信
64     while (1)
65     {
66         //接受数据
67         char buf[1024];
68         memset(buf, sizeof(buf), 0);
69         int len = read(cfd, buf, sizeof(buf));
70         if (len > 0)
71         {
72             printf("客户端说:%s\n", buf);
73 
74             //回复客户端
75             memset(buf, sizeof(buf), 0);
76             sprintf(buf, "你好,客户端,我已经收到了你的问候", sizeof(buf));
77             write(cfd, buf, len);
78         }
79         else if (len == 0)
80         {
81             printf("客户端断开了连接。。。\n");
82             break;
83         }
84         else
85         {
86             perror("read");
87             break;
88         }
89     }
90     close(cfd);
91     close(lfd);
92 
93     return 0;
94 }

 

三、客户端的通信流程

  在单线程的情况下客户端通信的文件描述符只有一个,没有监听的文件描述符

  1,创建一个通信的套接字   

1   int cfd = socket();

  2.连接服务器,需要知道服务器绑定的ip和端口    

1 connect();

  3.与服务端通信

1 //接受数据
2 read(); //recv();
3 
4 //发送数据
5 write();//send()

  4.断开连接,关闭文件描述符

close();

  基于tcp通信的客户端

 1 //客户端,client.c
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 #include <string.h>
 6 #include <arpa/inet.h>
 7 
 8 int main()
 9 {
10     //1.创建通信的套接字
11     int fd = socket(AF_INET, SOCK_STREAM, 0);
12     if (fd == -1)
13     {
14         perror("socket");
15         exit(0);
16     }
17 
18     //2.连接服务器
19     struct sockaddr_in addr;
20     addr.sin_family = AF_INET;
21     addr.sin_port = htons(10000);
22     //addr.sin_addr.s_addr = 
23     inet_pton(AF_INET, "192.168.0.23", &addr.sin_addr.s_addr);
24     int ret =connect(fd, (struct sockaddr*)&addr, sizeof(addr));
25     if (ret == -1)
26     {
27         perror("connect");
28         exit(0);
29     }
30 
31     //3.和服务端通信
32     int  number = 0;
33     while (1)
34     {
35         //发送数据
36         char buf[1024];
37         sprintf(buf, "您好,服务器。。。%d", number++);
38         write(fd, buf, sizeof(buf));
39 
40         //接受数据
41         memset(buf, 0, sizeof(buf));
42         int len = read(fd, buf, sizeof(buf));
43         if (len > 0)
44         {
45             printf("服务器说:%s\n", buf);
46         }
47         else if (len == 0)
48         {
49             printf("服务器断开了连接。。。\n");
50             break;
51         }
52         else
53         {
54             perror("read");
55             break;
56         }
57         sleep(1); //没隔一秒发送一条数据
58     }
59 }

5.最后,先启动服务端,再启动客户端,效果如下

服务端:

 

 客户端:

 

标签:addr,int,通信,TCP,socket,sizeof,include,buf,客户端
From: https://www.cnblogs.com/py369/p/17808677.html

相关文章

  • Modbus TCP/IP通讯,Modbus RTU通讯,Modbus ASCII通讯
    三种通信方式:ModbusTCP/IP通讯,ModbusRTU通讯,ModbusASCII通讯 【ModbusTCP/IP】硬件接口为RJ45,即网口。  连接时注意设置为同一网段和端口号:一对一时,一根网线直连即可。一对多时,用工业以太网交换机将所有设备接入交换机,通过不同的IP地址访问不同的设备。【ModbusR......
  • 晨控CK-GW08系列网关控制器与CODESYS软件MODBUSTCP通讯手册
    晨控CK-GW08系列网关控制器与CODESYS软件MODBUSTCP通讯手册晨控CK-GW08系列是一款支持标准工业通讯协议ModbusTCP的网关控制器,方便用户集成到PLC等控制系统中。系统还集成了8路读写接口,用户可通过通信接口使用ModbusTCP协议对8路读写接口所连接的读卡器进行相对独立的读写操作。......
  • PLC 和Modbus/串口设备现场总线通信及短信报警解决方案
    在实现Modbus设备与PROFIBUSDP协议PLC通讯的同时可以在手机端实时的接收报警短信,使客户足不出户了解设备与PLC的状态,及时处理现场中的问题。系统组成Modbus转PROFIBUSDP网关PM-160V6.2具有两个串口,一个RS485,一个RS232,他们一个做通讯接口时,另一个就作为IOT接口,该......
  • TCP协议
    引言在之前的内容中,我们已经详细讲解了TCP面试中最常见的问题,如三次握手和四次挥手等。而今天,我们将继续深入探讨TCP协议的其他方面,比如序列号和TCPFastOpen(TFO)等重要细节问题。这些内容将为你在面试中提供更全面的知识储备。为什么SYN/FIN不包含数据却要消耗⼀个序列号?SYN......
  • 使用websocket开发智能聊天机器人
    前面我们学习了异步web框架(sanic)和http异步调用库httpx,今天我们学习websocket技术。websocket简介我们知道HTTP协议是:请求->响应,如果没有响应就一直等着,直到超时;但是有时候后台的处理需要很长时间才能给到结果,比如30分钟,那HTTP的请求不可能等这么久,所以,可以通过Ajax轮询来解决。......
  • 你以为你了解TCP协议?这些你可能不知道的细节才是关键!
    引言在之前的内容中,我们已经详细讲解了TCP面试中最常见的问题,如三次握手和四次挥手等。而今天,我们将继续深入探讨TCP协议的其他方面,比如序列号和TCPFastOpen(TFO)等重要细节问题。这些内容将为你在面试中提供更全面的知识储备。为什么SYN/FIN不包含数据却要消耗⼀个序列号?SYN......
  • EtherNET/IP转Mpdbus Tcp协议网关协议
    EtherNET/IP转MpdbusTcp协议网关协议 JM-EIP-TCP是一款ETHERNET/IP从站功能的通讯网关。该产品主要功能是将各种MODBUS-TCP设备接入到ETHERNET/IP网络中。本网关连接到ETHERNET/IP总线中做为从站使用,连接到MODBUS-TCP总线中做为主站(客户端)或从站(服......
  • JAVA多线程之线程间的通信方式
    一,介绍本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。 二,线程间的通信方式①同步这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信。参考示例:publicclassMyObj......
  • 7. 从零开始编写一个类nginx工具, HTTP及TCP内网穿透原理及运行篇
    wmproxywmproxy是由Rust编写,已实现http/https代理,socks5代理,反向代理,静态文件服务器,内网穿透,配置热更新等,后续将实现websocket代理等,同时会将实现过程分享出来,感兴趣的可以一起造个轮子法项目++wmproxy++gite:https://gitee.com/tickbh/wmproxygithub:https://github.com/tic......
  • WSD、USB 和 TCP/IP 端口是连接和使用打印机的三种不同方法
    WSD、USB和TCP/IP端口是连接和使用打印机的三种不同方法,各自的特点如下:WSD(WebServicesonDevices)端口:WSD是一种基于网络的打印服务,允许计算机和打印机在局域网中通过网络发现彼此。它使用的是一种标准的网络协议,支持动态设备发现和配置。通常用于无线和有线的网络打......