Linux网络编程——tcp套接字

文章目录

    • 主要代码
    • 关于构造
    • listen监听
    • accept
    • telnet测试
    • 读取信息
    • 掉线重连
    • 翻译服务器演示

本章Gitee仓库:tcp套接字

主要代码

客户端:

#pragma once#include"Log.hpp"#include<iostream>
#include<cstring>#include<sys/wait.h>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>#include"threadPool.hpp"
#include"Task.hpp"const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";
const int backlog = 5;  //不要设置太大
Log log;enum{USAGE_ERR = 1,SOCKET_ERR,BIND_ERR,LITSEN_ERR
};
class TcpServer;class ThreadData
{
public:ThreadData(int fd, const std::string &ip, const uint16_t &port, TcpServer *t):t_sockfd_(fd), t_clientip_(ip), t_clientport_(port), t_tsvr_(t){}
public:int t_sockfd_;std::string t_clientip_;uint16_t t_clientport_;TcpServer *t_tsvr_; //需要this指针
};class TcpServer
{public:TcpServer(const uint16_t &port, const std::string &ip = defaultip):listensockfd_(defaultfd),port_(port),ip_(ip){}//初始化服务器void Init(){//创建套接字listensockfd_ = socket(AF_INET, SOCK_STREAM, 0); //sock_stream提供字节流服务--tcpif(listensockfd_ < 0){log(Fatal, "create socket, errno: %d, errstring: %s",errno, strerror(errno));exit(SOCKET_ERR);}log(Info, "create socket success, sockfd: %d",listensockfd_);int opt = 1;setsockopt(listensockfd_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));  //防止偶发性服务器无法进行立即重启//本地套接字信息struct sockaddr_in local;memset(&local, 0, sizeof(local));//填充网络信息local.sin_family = AF_INET;local.sin_port = htons(port_);inet_aton(ip_.c_str(), &(local.sin_addr));//bindint bd = bind(listensockfd_, (struct sockaddr*)&local, sizeof(local));if(bd < 0){log(Fatal, "bind error, errno: %d, errstring: %s",errno, strerror(errno));exit(BIND_ERR);}log(Info, "bind success");//tcp面向连接, 通信之前要建立连接//监听if(listen(listensockfd_, backlog) < 0){log(Fatal, "listen error, errno: %d, errstring: %s",errno, strerror(errno));exit(LITSEN_ERR);}log(Info, "listen success");}static void *Routine(void *args){pthread_detach(pthread_self());//子线程无需关闭文件描述符ThreadData *td = static_cast<ThreadData*>(args);td->t_tsvr_->Service(td->t_sockfd_, td->t_clientip_, td->t_clientport_);delete td;}void Start(){signal(SIGPIPE, SIG_IGN);threadPool<Task>::GetInstance()->Start();//signal(SIGCHLD, SIG_IGN);  //直接忽略进程等待 V2log(Info, "server is running...");while(true){//获取新链接struct sockaddr_in client;socklen_t len = sizeof(client);int sockfd = accept(listensockfd_, (struct sockaddr*)&client, &len);if(sockfd < 0){log(Warning, "accpet error, errno: %d, errstring: %s",errno, strerror(errno));continue;}uint16_t clientport = ntohs(client.sin_port);char clientip[32];inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));log(Info, "get a new link..., sockfd: %d, clientip: %s, clientport: %d", sockfd, clientip, clientport);//根据新链接进行通信//V1--单进程//Service(sockfd, clientip, clientport);//close(sockfd);//V2--多进程// pid_t id = fork();// if(id == 0)// {//     //child//     close(listensockfd_);  //子进程可以看到父进程的文件描述符表,关闭不需要的 //     if(fork() > 0)  exit(0);//父进程创建的子进程直接退出//     Service(sockfd, clientip, clientport);  //孙子进程执行, 由于孙子的父进程退出, 由系统领养//     close(sockfd);//     exit(0);// }// //father// close(sockfd);  //存在引用计数,不会这个关闭这个文件// pid_t tid = waitpid(id, nullptr, 0);// (void)tid;//V3--多线程(创建进程成本较高,换线程)// ThreadData *td = new ThreadData(sockfd, clientip, clientport, this);// pthread_t tid;// pthread_create(&tid, nullptr, Routine, td);//pthread_join(tid, nullptr);   //已进行线程分离,无需等待(并发执行)//V4--线程池Task t(sockfd, clientip, clientport);threadPool<Task>::GetInstance()->Push(t);//sleep(1); }}void Service(int sockfd, const std::string &clientip, const uint16_t &clientport){char buffer[4096];while(true){ssize_t n = read(sockfd, buffer, sizeof(buffer));if(n > 0){buffer[n] = 0;std::cout << "client say# " << buffer << std::endl;std::string echo_str = "tcpserver echo# ";echo_str += buffer;write(sockfd, echo_str.c_str(), echo_str.size());}else if(n == 0){log(Info, "%s:%d quit, server close sockfd: %d", clientip.c_str(), clientport, sockfd);break;}else{log(Warning, "read error, sockfd: %d, clientip: %s, clientport: %d", sockfd, clientip.c_str(), clientport);break;}memset(buffer, 0, sizeof(buffer));}}~TcpServer(){}
private:int listensockfd_;uint16_t port_;std::string ip_;
};

客户端:

#include<iostream>
#include<cstring>
#include<unistd.h>#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>void Usage(const std::string &proc)
{std::cout << "\n\tUsage: " << proc << "serverip serverport" << std::endl;
}int main(int argc, char *argv[])
{if(argc != 3){Usage(argv[0]);exit(1);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);// 填充信息struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);inet_pton(AF_INET, serverip.c_str(), &(server.sin_addr));//连接模块while (true){int sockfd = 0;int cnt = 5;bool isreconnect = false;sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){std::cerr << "socket error" << std::endl;return 1;}do{// tcp客户端也无需显示bind// 向目标发起连接(connect的时候进行自动随机bind)int cn = connect(sockfd, (struct sockaddr *)&server, sizeof(server));if (cn < 0){isreconnect = true;cnt--;  //重连5秒std::cerr << "connet error, reconnect: " << cnt << std::endl;close(sockfd);sleep(1);   //每隔一秒重连一次}else{break;}}while(cnt && isreconnect);if(cnt == 0){std::cerr << "server offline..." << std::endl;break;}//服务模块//while (true){std::string message;std::cout << "Please Enter# ";std::getline(std::cin, message);if (message.empty())continue;int wn = write(sockfd, message.c_str(), message.size());if (wn < 0){std::cerr << "write error" << std::endl;//break;}char inbuffer[4096];int rn = read(sockfd, inbuffer, sizeof(inbuffer));if (rn > 0){inbuffer[rn] = 0;std::cout << inbuffer << std::endl;}else{//break;}}close(sockfd);}return 0;
}

关于构造

关于构造和初始化,可以直接在构造的时候,将服务器初始化,那为什么还要写到init初始化函数里面呢?

构造尽量简单一点,不要做一些“有风险”的操作。

listen监听

tcp是面向连接的,通信之前要建立连接,服务器处于等待连接到来的状态:

#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);

image-20240205161303727

accept

获取新链接:

#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

后两个参数输出型参数,获取对方的信息

这里返回也是一个套接字,这和最开始创建的listensockfd_有什么区别呢?

这就好比去吃饭,门口有一个拉客的,问“帅哥,来不来我们这里吃饭啊”,如果你去了,那就是“欢迎光临,几位呀”,你回答“我和我女朋友”,然后这个人大喊“两位客人,来一个服务员”,这时候就来了一个服务员招呼你坐下,然后给你菜单,点完菜之后给你上菜;在这个期间站在门口的拉客的人,一直在招揽客人,有人来就喊服务员招招待,人家不来就继续拉。

listensockdf_就是这个拉客的,真正给我们提供服务的是accept返回的

telnet测试

telnet可以对指定服务的远程连接

image-20240205192444936

127.0.0.1本地环回,再加上端口号就可以测试了

ctrl + ],然后回车

读取信息

tcp是面向字节流的,管道是面向字节流的、读取普通文件也是面向字节流的,所以可以采用read进行读取。

掉线重连

当读端关闭之后,系统会杀掉写端,采用signal(SIGPIPE, SIG_IGN)忽略这个信号

翻译服务器演示

GIF 2024-2-11 20-17-30

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/678843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第73左侧菜单实现

layout下面新建menu layout index.vue导入menu import Menu from /views/layout/menu菜单实现&#xff1a; <template><el-menuactive-text-color"#ffd04b"background-color"#2d3a4b"class"el-menu-vertical-demo"default-active&quo…

灰度发布浅见

在之前的稳定性生产文章中有一项对于研发人员比较重要的措施是变更管控&#xff0c;关于变更管控其实在实际生产活动中有很多措施&#xff0c;因为对于不太的行业&#xff0c;其行业特点和稳定性生产的要求也不一样&#xff0c;例如下图&#xff0c;我们可以看到信通院调研的不…

【开源】SpringBoot框架开发APK检测管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 开放平台模块2.3 软件档案模块2.4 软件检测模块2.5 软件举报模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 开放平台表3.2.2 软件档案表3.2.3 软件检测表3.2.4 软件举报表 四、系统展示五、核心代…

【el-tree 文字过长处理方案】

文字过长处理方案 一、示例代码二、关键代码三、效果图 一、示例代码 <divstyle"height: 600px;overflow: auto"class"text item"><el-treeref"tree":data"treeData":props"defaultProps"class"filter-tree&…

计算机网络——05Internet结构和ISP

Internet结构和ISP 互连网络结构&#xff1a;网络的网络 端系统通过接入ISPs连接到互连网 住宅、公司和大学的ISPs 接入ISPs相应的必须是互联的 因此任何2个端系统可相互发送分组到对方 导致的“网络的网络”非常复杂 发展和演化是通过经济的和国家的政策来驱动的 问题&…

课堂秩序要求有哪些内容

你是否曾经疑惑&#xff0c;为什么有些课堂总是秩序井然&#xff0c;而有些则混乱不堪&#xff1f;作为一位经验丰富的老师&#xff0c;我想告诉你&#xff0c;课堂秩序不仅仅是学生安静听讲那么简单&#xff0c;它背后涉及到许多关键因素&#xff0c;直接影响着教学质量和学习…

postgresql 手动清理wal日志的101个坑

新年的第一天&#xff0c;总结下去年遇到的关于WAL日志清理的101个坑&#xff0c;以及如何相对安全地进行清理。前面是关于WAL日志堆积的原因分析&#xff0c;清理相关可以直接看第三部分。 首先说明&#xff0c;手动清理wal日志是一个高风险的操作&#xff0c;尤其对于带主从的…

CleanMyMac X 4.14.7帮您安全清理Mac系统垃圾

CleanMyMac X 4.14.7是一款强大的 Mac 清理、加速工具和健康卫士,可以让您的 Mac 再次恢复巅峰性能。 移除大型和旧文件、卸载应用,并删除浪费磁盘空间的无用数据。 5倍 更多可用磁盘空间 CleanMyMac X 4.14.7帮您安全清理Mac系统垃圾 CleanMyMac X 4.14.7一键深度扫描mac系统…

Java常用类与基础API--String的理解与不可变性

文章目录 一、字符串相关类之不可变字符序列&#xff1a;String&#xff08;1&#xff09;对String类的理解(以JDK8为例说明)1、环境2、类的声明3、内部声明的属性 &#xff08;2&#xff09;String的特性&#xff08;3&#xff09;字符串常量的存储位置1、举例2、String的存储…

「优选算法刷题」:数青蛙

一、题目 给你一个字符串 croakOfFrogs&#xff0c;它表示不同青蛙发出的蛙鸣声&#xff08;字符串 "croak" &#xff09;的组合。由于同一时间可以有多只青蛙呱呱作响&#xff0c;所以 croakOfFrogs 中会混合多个 “croak” 。 请你返回模拟字符串中所有蛙鸣所需不…

Day39- 动态规划part07

一、爬楼梯 题目一&#xff1a;57. 爬楼梯 57. 爬楼梯&#xff08;第八期模拟笔试&#xff09; 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬至多m (1 < m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a;…

【大厂AI课学习笔记】【1.6 人工智能基础知识】(3)神经网络

深度学习是机器学习中一种基于对数据进行表征学习的算法。观测值(例如一幅草莓照片)可以使用 多种方式来表示&#xff0c;如每个像素强度值的向量&#xff0c;或者更抽象地表示成一系列边、特定形状的区域等。 深度学习的最主要特征是使用神经网络作为计算模型。神经网络模型 …

深入理解 Nginx 插件及功能优化指南

深入理解 Nginx 插件及功能优化指南 深入理解 Nginx 插件及功能优化指南1. Nginx 插件介绍1.1 HTTP 模块插件ngx_http_rewrite_modulengx_http_access_module 1.2 过滤器插件ngx_http_gzip_modulengx_http_ssl_module 1.3 负载均衡插件ngx_http_upstream_modulengx_http_upstre…

CSS Selector—选择方法,和html自动——异步社区的爬取(动态网页)——爬虫(get和post的区别)

这里先说一下GET请求和POST请求&#xff1a; post我们平时是要加data的也就是信息&#xff0c;你会发现我们平时百度之类的 搜索都是post请求 get我们带的是params&#xff0c;是发送我们指定的内容。 要注意是get和post请求&#xff01;&#xff01;&#xff01; 先说一下异…

python+django人力资源管理系统7w5x3

技术栈 后端&#xff1a;python 前端&#xff1a;vue.jselementui 框架&#xff1a;django Python版本&#xff1a;python3.7 数据库&#xff1a;mysql5.7 数据库工具&#xff1a;Navicat 开发软件&#xff1a;PyCharm .设计框架&#xff1a;Vue 1. 表现层&#xff1a;写多…

JCIM | MD揭示PTP1B磷酸酶激活RtcB连接酶的机制

Background 内质网应激反应&#xff08;UPR&#xff09; 中的一个重要过程。UPR是由内质网中的三种跨膜传感器&#xff08;IRE1、PERK和ATF6&#xff09;控制的细胞应激反应&#xff0c;当内质网中的蛋白质折叠能力受到压力时&#xff0c;UPR通过减少蛋白质合成和增加未折叠或错…

《计算思维导论》笔记:10.4 关系模型-关系运算

《大学计算机—计算思维导论》&#xff08;战德臣 哈尔滨工业大学&#xff09; 《10.4 关系模型-关系运算》 一、引言 本章介绍数据库的基本数据模型&#xff1a;关系模型-关系运算。 二、什么是关系运算 在数据库理论中&#xff0c;关系运算&#xff08;Relational Operatio…

蓝桥杯Web应用开发-CSS3 新特性【练习一:属性有效性验证】

练习一&#xff1a;属性有效性验证 页面上有一个邮箱输入框&#xff0c;当你的输入满足邮箱格式时&#xff0c;输入框的背景颜色为绿色&#xff1b;当你的输入不满足要求&#xff0c;背景颜色为红色。 新建一个 index2.html 文件&#xff0c;在其中写入以下内容。 <!DOCTYP…

读书笔记之《重塑大脑重塑人生》:大脑强大的可塑性

《重塑大脑重塑人生》作者是诺曼道伊奇&#xff0c;原作名: The Brain That Changes Itself: Stories of Personal Triumph from the Frontiers of Brain Science &#xff0c;于 2015-1-20出版。 诺曼•道伊奇&#xff08;Norman Doidge&#xff09;是医学博士&#xff0c;精…

【JavaEE】传输层网络协议

传输层网络协议 1. UDP协议 1.1 特点 面向数据报&#xff08;DatagramSocket&#xff09;数据报大小限制为64k全双工不可靠传输有接收缓冲区&#xff0c;无发送缓冲区 UDP的特点&#xff0c;我理解起来就是工人组成的**“人工传送带”**&#xff1a; 面向数据报&#xff08;…