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通信流程以及代码实现 的相关文章

  • docker容器大小远大于实际大小

    我正在尝试从中构建图像debian latest 构建后 报告的图像虚拟大小来自docker images命令为 1 917 GB 我登录查看尺寸 du sh 大小为 573 MB 我很确定这么大的尺寸通常是不可能的 这里发生了什么 如何获
  • 在脚本内使用不带密码的 sudo

    由于某种原因 我需要作为用户在没有 sudo 的情况下运行脚本 script sh 该脚本需要 root 权限才能工作 我认为将 sudo 放入 script sh 中是唯一的解决方案 让我们举个例子 script sh bin sh su
  • 如何使用 GOPATH 的 Samba 服务器位置?

    我正在尝试将 GOPATH 设置为共享网络文件夹 当我进入 export GOPATH smb path to shared folder I get go GOPATH entry is relative must be absolute
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • 我不明白 execlp() 在 Linux 中如何工作

    过去两天我一直在试图理解execlp 系统调用 但我还在这里 让我直奔主题 The man pageexeclp 将系统调用声明为int execlp const char file const char arg 与描述 execl exe
  • 如何在基于 Linux 的系统上的 C 程序中使用 mqueue?

    如何在基于 Linux 的系统上的 C 程序中使用 mqueue 消息队列 我正在寻找一些好的代码示例 可以展示如何以正确且正确的方式完成此操作 也许是一个操作指南 下面是一个服务器的简单示例 该服务器接收来自客户端的消息 直到收到告诉其停
  • Linux:如何设置进程的时区?

    我需要设置在 Linux 机器上启动的各个进程的时区 我尝试设置TZ变量 在本地上下文中 但它不起作用 有没有一种方法可以使用与系统日期不同的系统日期从命令行运行应用程序 这可能听起来很愚蠢 但我需要一种sandbox系统日期将被更改的地方
  • 进程退出后 POSIX 名称信号量不会释放

    我正在尝试使用 POSIX 命名信号量进行跨进程同步 我注意到进程死亡或退出后 信号量仍然被系统打开 在进程 打开它 死亡或退出后是否有办法使其关闭 释放 早期的讨论在这里 当将信号量递减至零的进程崩溃时 如何恢复信号量 https sta
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost
  • 如何构建任务“gems:install”

    我正在将 Rails 应用程序部署到 Linux 服务器 并且缺少一些 rake 任务 包括 rake gems install 和 rake db 我正在运行来自 GEM 的 Rails 2 3 4 为什么是这样 我该如何解决 我可以以某
  • Windows CE 与嵌入式 Linux [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 现在我确信我们都清楚 Linux 与 Windows 桌面的相对优点 然而 我对嵌入式开发世界的了解却少得多 我主要对行业解决方案感兴
  • 捕获实时流量时如何开启纳秒精度?

    如何告诉 libpcap v1 6 2 将纳秒值存储在struct pcap pkthdr ts tv usec 而不是微秒值 捕获实时数据包时 Note This question is similar to How to enable
  • 如何允许应用程序声明“https”方案 URI? (即如何从 https URL 打开桌面应用程序?)

    目前我正在尝试为 OAuth 2 0 授权流程创建一个客户端 实际上是一个本机应用程序 并且在规范中就在这儿 https www rfc editor org rfc rfc8252 section 7 2据说有 3 种方法来处理重定向 U
  • 为什么C Clock()返回0

    我有这样的事情 clock t start end start clock something else end clock printf nClock cycles are d d n start end 我总是得到输出 时钟周期是 0
  • 在 unix 中编译 dhrystone 时出错

    我是使用基准测试和 makefile 的新手 我已经从下面的链接下载了 Dhrystone 基准测试 我正在尝试编译它 但我遇到了奇怪的错误 我尝试解决它 但没有成功 有人可以帮助我运行 dhrystone 基准测试吗 以下是我尝试编译的两
  • 无法在 Perl 中找到 DBI.pm 模块

    我使用的是 CentOS 并且已经安装了 Perl 5 20 并且默认情况下存在 Perl 5 10 我正在使用 Perl 5 20 版本来执行 Perl 代码 我尝试使用 DBI 模块并收到此错误 root localhost perl
  • Python 脚本作为 Linux 服务/守护进程

    Hallo 我试图让 python 脚本作为服务 守护进程 在 ubuntu linux 上运行 网络上存在多种解决方案 例如 http pypi python org pypi python daemon http pypi python
  • 从 systemd bash 内联脚本创建 filename_$(date %Y-%m-%d)

    我正在尝试执行systemd计时器并希望将执行脚本的输出保存在每个日期的文件中 这是我的ExecStart脚本中的 service file ExecStart bin bash c echo date Y m d gt gt home u
  • 每个命令都返回“bash:<命令>:找不到命令...”[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我刚刚安装了 Scala 并添加了路径gedit bashrc export SCALA HOME home avijit sca
  • 让 TeXstudio 在 linux mint 中工作:找不到文件“url.sty”。

    刚刚切换到 Linux Mint 以前的顽固 Windows 用户 我在尝试安装 TeXstudio 时遇到一些问题 Sudo apt get install texstudio 给了我一个正确的安装 至少 我是这么认为的 但是当我尝试构建

随机推荐

  • 复睿智行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