linux---tcp通信流程以及代码实现

2023-05-16

TCP通信特性:(在网络版块详细讲解)
面向连接
可靠
面向字节流

TCP通信过程
在这里插入图片描述

c++封装TCP通信

  1 #include <iostream>
  2 #include <arpa/inet.h>
  3 #include <unistd.h>
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <string.h>
  7 #include <string>
  8 #include <errno.h>
  9 #include <netinet/in.h>
 10 #include <sys/socket.h>
 11 #define CHECK(T) if((T) == false) {return -1;}
 12 class TcpSocket{
 13     public:
 14         bool Close(){
 15             int ret = close(_sock);
 16             if(ret < 0){
 17                 perror("close error\n");
 18                 return false;
 19             }
 20             _sock = -1;
 21             return true;
 22         }
 23         TcpSocket():_sock(-1){
 24         };
 25         ~TcpSocket(){
 26         };
 27         bool Socket(){
 28             int ret = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 29             if(ret < 0){
 30                 perror("socket error\n");
 31                 return false;
 32             }
 33             _sock = ret;
 34             return true;
 35         }
 36         bool Bind(std::string& ip,uint16_t port){
 37             struct sockaddr_in  ser_addr;
 38             ser_addr.sin_family = AF_INET;
 39             ser_addr.sin_port = htons(port);
 40             ser_addr.sin_addr.s_addr = inet_addr(ip.c_str());
 41             socklen_t len = sizeof(ser_addr);
 42             int ret = bind(_sock,(struct sockaddr*)&ser_addr,len);
 43             if(ret < 0){
 44                 perror("bind error\n");
 45                 return false;
 46             }
 47             return true;
 48         }
 49         bool Listen(int backlog = 10){
 50             int ret = listen(_sock,backlog);
 51             if(ret < 0){
 52                 perror("listen error\n");
 53                 return false;
 54             }
 55             return true;
 56         }
 57         bool Connect(std::string& ip,uint16_t port){
 58             //给定服务器端的地址
 59             struct sockaddr_in addr;
 60             addr.sin_family = AF_INET;
 61             addr.sin_port = htons(port);
 62             addr.sin_addr.s_addr = inet_addr(ip.c_str());
 63             socklen_t len = sizeof(addr);
 64             int ret = connect(_sock,(struct sockaddr*)&addr,len);
 65             if(ret < 0){
 66                 perror("connect error\n");
 67                 return false;
 68             }
 69             return true;
 70         }
 71         bool Accept(TcpSocket& csock,struct sockaddr_in *cli = NULL){
 72             struct sockaddr_in _addr;
 73             socklen_t len = sizeof(_addr);
 74             int newfd = accept(_sock,(struct sockaddr*)&_addr,&len);
 75             if(newfd < 0){
 76                 perror("accept error\n");
 77                 return false;
 78             }
 79             //需要将获取的客户端的信息拷贝出去
 80             memcpy(cli,&_addr,len);
 81             csock.setSock(newfd);
 82             return true;
 83 
 84         }
 85         void setSock(int sock){
 86             _sock = sock;
 87         }
 88         bool Recv(std::string& str){
 89             char temp[1024] = {0};
 90             //设置成0默认是阻塞的
 91             int ret = recv(_sock,temp,1024,0);
 92             //返回-1出错,返回0客户端关闭,其余返回接受到的数据大小
 93             if(ret < 0){
 94                 perror("recv error\n");
 95                 return false;
 96             }
 97             if(ret == 0){
 98                 std::cout << "客户端已经断开了连接" << std::endl;
 99                 return false;
100             }
101             str.assign(temp,ret);
102             return true;
103         }
104         bool Send(std::string& str){
105             int ret = send(_sock,str.c_str(),str.size(),0);
106             if(ret < 0){
107                 perror("send error\n");
108                 return false;
109             }
110             return true;
111         }
112     private:
113         int  _sock;
114 };

**重点:**我们tcp通信时需要使用多线程或者多进程来进行多个客户端的连接请求,不然只能连接一个请求。

多进程服务端版本

  1 #include "tcpsocket.hpp"
  2 #include <signal.h>
  3 #include <sys/wait.h>
  4 
  5 void sigbc(int num){
  6     while(waitpid(-1,NULL,WNOHANG)>0);
  7 }
  8 
  9 int main(int argc,char* argv[]){
 10     if(argc != 3){
 11         perror("tcp_ser ip port\n");
 12         return -1;
 13     }
 14     std::string ip = argv[1];
 15     uint16_t port = atoi(argv[2]);
 16     signal(SIGCHLD,sigbc);
 17     TcpSocket sock;
 18     CHECK(sock.Socket());
 19     CHECK(sock.Bind(ip,port));
 20     CHECK(sock.Listen(10));
 21     while(1){
 22         //创建一个通信
 23         TcpSocket com;
 24         struct sockaddr_in cli;
 25         if(sock.Accept(com,&cli) == false){
 26             continue;
 27         }
 28         std::cout<<"新的连接Ip:"<<inet_ntoa(cli.sin_addr);
 29         std::cout<<"端口port:"<<ntohs(cli.sin_port)<<std::endl;
 30         int pid = fork();
 31         if(pid == 0){
 32             while(1){
 33                 std::string buf;
 34                 com.Recv(buf);
 35                 std::cout<<"client said:"<<buf<<std::endl;
 36                 buf.clear();
 37                 std::cout<<"server say:";
 38                 std::cin>>buf;
 39                 fflush(stdout);
 40                 com.Send(buf);
 41             }
 42         }
 43         com.Close();
 44     }
 45     sock.Close();
 46     return 0;
 47 }

多线程服务端版本

 1 #include "tcpsocket.hpp"
  2 #include <pthread.h>
  3 void* start_thr(void* arg){
  4     TcpSocket* sock = (TcpSocket*)arg;
  5     while(1){
  6         std::string str;
  7         sock->Recv(str);
  8         std::cout<<"client said:"<<str<<std::endl;
  9         str.clear();
 10         
 11         std::cout<<"server say:";
 12         fflush(stdout);
 13         std::cin>>str;
 14         sock->Send(str);
 15     }
 16     delete sock;
 17     sock->Close();
 18     return NULL;
 19 }
 20 int main(int argc,char* argv[]){
 21     if(argc != 3){
 22         perror("./pro ip port\n");
 23         return -1;
 24     }
 25     std::string ip = argv[1];
 26     uint16_t port = atoi(argv[2]);
 27 
 28     TcpSocket sock;
 29     CHECK(sock.Socket());
 30     CHECK(sock.Bind(ip,port));
 31     CHECK(sock.Listen(10));
 32     while(1){
 33         struct sockaddr_in cli;
 34         //这里在堆上开辟空间,是线程共用
 35         TcpSocket* csock = new TcpSocket();
 36         if(sock.Accept(*csock,&cli) == false){
 37             continue;
 38         }
 39         std::cout<<"新的客户端IP:"<<inet_ntoa(cli.sin_addr);
 40         std::cout<<"  端口:"<<ntohs(cli.sin_port)<<std::endl;
 41         pthread_t pid;
 42         pthread_create(&pid,NULL,start_thr,(void*)csock);
 43         pthread_detach(pid);
 44     }
 45     sock.Close();
 46     return 0;
 47 }

客户端代码实现

1 #include "tcpsocket.hpp"
  2 
  3 int main(int argc,char* argv[]){
  4     if(argc != 3){
  5         perror("./tcp_cli ip port\n");
  6         return -1;
  7     }
  8     std::string ip = argv[1];
  9     uint16_t port = atoi(argv[2]);
 10 
 11     TcpSocket sock;
 12     CHECK(sock.Socket());
 13     CHECK(sock.Connect(ip,port));
 14     while(1){
 15         std::string buf;
 16         std::cout<<"client say:";
 17         fflush(stdout);
 18         std::cin>>buf;
 19         sock.Send(buf);
 20 
 21         buf.clear();
 22         sock.Recv(buf);
 23         std::cout<<"server said:"<<buf<<std::endl;
 24     }
 25     sock.Close();
 26     return 0;
 27 } 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux---tcp通信流程以及代码实现 的相关文章

  • 应用程序中两个不同版本的库

    考虑一个场景 其中有两个不同版本的共享库 考虑 A 1 so 链接到 B so A 2 so 链接到 C so 现在 B so 和 C so 都链接到 d exe 当 B so 想要调用 A 1 so 中的函数时 它最终会调用 A 2 so
  • 我想在 Red Hat Linux 服务器中执行 .ps1 powershell 脚本

    我有一个在窗口中执行的 ps1 powershell 脚本 但我的整个数据都在 Linux 服务器中 有什么可能的方法可以让我在红帽服务器中执行 powershell 脚本 powershell脚本是 Clear Host path D D
  • Linux中如何避免sleep调用因信号而中断?

    我在 Linux 中使用实时信号来通知串行端口中新数据的到达 不幸的是 这会导致睡眠呼叫在有信号时被中断 有人知道避免这种行为的方法吗 我尝试使用常规信号 SIGUSR1 但我不断得到相同的行为 来自 nanosleep 联机帮助页 nan
  • 在 scapy 中通过物理环回发送数据包

    我最近发现了 Scapy 它看起来很棒 我正在尝试查看 NIC 上物理环回模块 存根上的简单流量 但是 Scapy sniff 没有给出任何结果 我正在做的发送数据包是 payload data 10 snf sniff filter ic
  • 链接错误:命令行中缺少 DSO

    我对 Linux 使用 Ubuntu 14 04 LTS 64 位 相当陌生 来自 Windows 并且正在尝试移植我现有的 CUDA 项目 当通过链接时 usr local cuda bin nvcc arch compute 30 co
  • Crontab 每 5 分钟一次 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我如何告诉 crontab 每 5 分钟运行一次 但从每小时的第二分钟开始 换句话说 我想在以下时间执行我的脚本minute 5 2 例如 我的脚本应
  • “git add”返回“致命:外部存储库”错误

    我刚刚进入 git 的奇妙世界 我必须提交我对程序所做的一系列更改 位于名为的目录中 var www myapp 我创建了一个新目录 home mylogin gitclone 从这个目录中 我做了一个git clone针对公共回购 我能够
  • 在 x86 汇编语言中获取文件大小的简单方法

    假设我已经在汇编中打开了一个文件 并且在寄存器 eax 中有该文件的文件句柄 我将如何获取文件的大小 以便为其分配足够的缓冲区空间 我在这里研究了另一个讨论 建议使用sys fstat 28 系统调用来获取文件统计信息但无法实现它 My a
  • 如何并行执行4个shell脚本,我不能使用GNU并行?

    我有4个shell脚本dog sh bird sh cow sh和fox sh 每个文件使用 xargs 并行执行 4 个 wget 来派生一个单独的进程 现在我希望这些脚本本身能够并行执行 由于某些我不知道的可移植性原因 我无法使用 GN
  • LINUX:如何锁定内存中进程的页面

    我有一个 LINUX 服务器 运行一个具有大量内存占用的进程 某种数据库引擎 该进程分配的内存太大 需要将其中一部分换出 换出 我想做的是将所有其他进程 或正在运行的进程的子集 的内存页面锁定在内存中 以便只有数据库进程的页面被换出 例如
  • 如何从 C++ 程序中重新启动 Linux?

    我有一个 Qt 4 GUI 我需要在下拉菜单中提供一个选项 允许用户选择重新启动计算机 我意识到这对于以其他方式重新启动计算机的能力来说似乎是多余的 但选择需要保留在那里 我尝试使用 system 来调用以下内容 suid root she
  • 来自守护程序的错误响应:加入会话密钥环:创建会话密钥:超出磁盘配额

    我尝试在我的服务器上安装 docker 使用本教程 https docs docker com install linux docker ce ubuntu 我想远程运行 docker 镜像并使用 portainer Web 界面来管理一切
  • 在汇编中使用 printf 会导致管道传输时输出为空,但可以在终端上使用

    无输出 https stackoverflow com questions 54507957 printf call from assembly do not print to stdout即使在终端上 当输出不包含换行符时也有相同的原因
  • Java 客户端到服务器未知来源

    我有一个简单的乒乓球游戏 需要通过网络工作 服务器将创建一个带有球和 2 个球棒位置的游戏 当客户端连接到服务器时 服务器将创建一个名为 PongPlayerThread 的新类 它将处理客户端到服务器的输入和输出流 我的服务器工作100
  • 如何在 Linux 上通过 FTP 递归下载文件夹 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 如何在不使用 IDE 的情况下在 Linux 上运行 Java 项目

    我是 Java 新手 基本上 我开发了一个java项目 其中包含Eclipse中的多个Java包 该项目在我安装了 redhat Linux 的桌面上运行正常 然而 我需要在一个更强大的没有安装X11的Linux服务器 redhat ent
  • 如何才能将 TCP 连接返回到同一端口?

    机器是 RHEL 5 3 内核 2 6 18 有时我在 netstat 中注意到我的应用程序有连接 建立了 TCP 连接本地地址 and 国外地址是一样的 其他人也报告了同样的问题 症状与链接中描述的相同 客户端连接到本地运行的服务器的端口
  • 仅使用containerd(不使用Docker)修剪容器镜像

    如果我刚刚containerd安装在 Linux 系统上 即 Docker 是not安装 如何删除未使用的容器映像以节省磁盘空间 Docker 就是这么方便docker system prune https docs docker com
  • 执行命令而不将其保留在历史记录中[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 在进行软件开发时 经常需要在命令行命令中包含机密信息 典型示例是将项目部署到服务器的凭据设置为环境变量 当我不想将某些命令存储在命令历史记
  • SSH,运行进程然后忽略输出

    我有一个命令可以使用 SSH 并在 SSH 后运行脚本 该脚本运行一个二进制文件 脚本完成后 我可以输入任意键 本地终端将恢复到正常状态 但是 由于该进程仍在我通过 SSH 连接的计算机中运行 因此任何时候它都会登录到stdout我在本地终

随机推荐

  • 复睿智行CC++开发实习面试

    线上面试 xff0c HR和一位技术的面试官 自我介绍 现在研究生学习的方向是什么 xff1f 我还去答区块链 xff0c 本来就半桶水 xff0c 还不如直接回答C C 43 43 后端这个方向 大数据分析这一块有做过吗 xff1f 我
  • 经纬恒润LinuxC++日常实习面经

    自我介绍 在学校成绩如何 xff0c 有没有获得奖学金 xff0c 考研的时间等等相关问题 能实习多久 xff0c 研究生研究的方向 你这个LinuxC 43 43 开发的学习是自学的吗 xff0c 怎样的自学途径 我 xff1a 看书 看
  • 集群聊天服务器项目(三)——负载均衡模块与跨服务器聊天

    负载均衡模块 为什么要加入负载均衡模块 原因是 xff1a 单台服务器并发量最多两三万 xff0c 不够大 负载均衡器 Nginx的用处或意义 xff08 面试题 xff09 把client请求按负载算法分发到具体业务服务器Chatserv
  • C++校招面试题

    C 43 43 static关键字的作用 xff08 从elf结构 链接的过程 xff09 答 xff1a static可以修饰全局变量 函数 局部变量 xff0c 这些符号在加了staitc后就只能在当前文件可见 xff0c 其他文件不可
  • make_shared知识点

    背景 普通创建shared ptr的方法如 xff1a shared ptr span class token operator lt span span class token keyword int span span class to
  • emplace方法原理剖析

    emplace back 和 push back 的差别 有一个类Test定义如下 span class token keyword class span span class token class name Test span span
  • 【 rbx1翻译 第七章、控制移动基座】第八节、使用里程计进行往返运动

    7 8 Out and Back Using Odometry 使用里程计进行往返运动 现在 xff0c 我们了解了里程表信息是如何在ROS中表示的 xff0c 我们可以更精确地在往返过程中移动机器人 下一个脚本将监视 odom和 base
  • 项目总结一:串口通信 || 串口接收数据和写入的数据不一致

    在做项目串口通信时遇到一个奇怪的bug xff0c 我写入的一个两个字节short类型数据3 xff0c 接受到的数据很奇怪有时是一个很大的数 xff0c 有时又是300多 xff0c 为了找到原因也是废了一些时间 xff0c 这里给分享一
  • linux---套接字编程

    一 Socket是什么 1 socket套接字 xff1a socket起源于Unix xff0c 而Unix Linux基本哲学之一就是 一切皆文件 xff0c 都可以用 打开open gt 读写write read gt 关闭close
  • ROS订阅者只订阅一次消息

    include lt ros ros h gt include lt opencv2 core core hpp gt include lt opencv2 imgproc imgproc hpp gt include lt opencv2
  • 【FPGA练习】(一): UART串口通信实验

    由于之前学习FPGA的过程中 xff0c 没有做一个良好的记录 xff0c 以及已学知识的扩展 xff0c 所以从今天开始每一个实验例程和扩展应用 xff0c 都要做文档记录 本实验 xff0c 是基于正点原子达芬奇xc7a35tfgg48
  • Ubuntu配置GStreamer实现python推流

    想用python实现一个推流服务 xff0c 下面记录一下配置过程 系统是ubuntu18 04 xff0c python3 6和3 8中都试过 1 安装gstreamer sudo apt get install libgstreamer
  • CMake 引用第三方库

    一 cmake简介 cmake 是gnu工具链中构建项目重要的一环 xff0c 而且在windows linux OS X中都可以使用 xff0c 特别是linux C C 43 43 程序员必备基本功 二 基本命令 xff1a 命名变量
  • C/C++:struct和class区别

    C和C 43 43 中的Struct区别 CC 43 43 不能将函数放在结构体声明能将函数放在结构体声明在C结构体声明中不能使用C 43 43 访问修饰符 public protected private 在C 43 43 中可以使用 在
  • 四旋翼无人机学习之准备篇(一)

    最近我哥要给我邮递个四旋翼无人机 xff0c 再加上本人对蓝天从小就很感兴趣 所以在学习完四驱小车后打算上手下无人机 刚开始学习根本不知道要看哪些 xff0c 在几天漫无头绪的学习 xff0c 终于有点气色了 xff0c 就把学习经验分享给
  • 更改Ubuntu默认python版本的方法

    可以按照以下方法使用 ls 命令来查看你的系统中都有那些 Python 的二进制文件可供使用 1 2 ls usr bin python usr bin python usr bin python2 usr bin python2 7 us
  • c++求素数

    C 43 43 练习第一课 C 43 43 输入一个n 求n以内的素数 xff1a C 43 43 输入一个n 求n以内的素数 xff1a include span class token operator lt span iostream
  • 贪吃蛇

    C尝试写的贪吃蛇项目 xff08 数组实现 xff09 以后会更新用链表实现贪吃蛇 span class token macro property span class token directive keyword define span
  • Android公司面试题

    Android 面试题及面试经验 我的第一次面试经验 今天来到成都面试 xff0c 面试的是Android xff0c 说实话 xff0c Android并不是我的强项 xff0c 只是在大学期间接触过 第一关人事还可以 xff0c 第二关
  • linux---tcp通信流程以及代码实现

    TCP通信特性 xff1a xff08 在网络版块详细讲解 xff09 面向连接 可靠 面向字节流 TCP通信过程 c 43 43 封装TCP通信 1 include lt iostream gt 2 include lt arpa ine