Linux——网络通信TCP通信常用的接口和tcp服务demo
文章目录
- TCP通信所需要的套接字
- socket()
- bind()
- listen()
- accept
- connect()
- 封装TCP socket
TCP通信所需要的套接字
socket()
socket()函数主要作用是返回一个描述符,他的作用就是打开一个网络通讯端口,返回的这个描述符其实就可以理解为一个文件描述符,tcp在通讯的时候是会开辟一个缓存空间的,我们发送和读取消息可以理解为在这个缓存空间中进行的。因此这里我们可以知道我们可以直接用write和read函数进行消息的写入和读取,如果socket()调用出错则返回-1;
对于IPv4, family参数指定为AF_INET;
对于TCP协议,type参数指定为SOCK_STREAM, 表示面向流的传输协议
protocol参数的介绍从略,指定为0即可。
代码如下以ipv4协议为例
int socketfd=socket(AF_INET,SOCK_STREAM,0);
bind()
bind()函数的作用是为了让socket返回的描述符与端口号进行绑定在bind函数之前我们还需要做一个工作就是将我们的信息存入一个结构体sockaddr_in中,struct sockaddr *是一个通用指针类型,myaddr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度

我们的程序中对myaddr参数是这样初始化的:
sockaddr_in local;
bzero(&local, sizeof(local));//将整个结构体清0
local.sin_port = htons(port_);//porty_是我们的端口号这里是将这个端口号转化为网络序列一般我们的端口号都设置为8000以上
local.sin_family = AF_INET;//设置地址类型为AF_INET
inet_aton(ip_.c_str(), &(local.sin_addr));//网络地址为INADDR_ANY, 这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP 地址, 这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP 地址;
listen()

liasten函数生命socketfd正处于监听状态并且最多可以允许backlog个客户端处于连接等待状态如果收到更多连接请求就会忽略
listen成功返回0 失败则是-1
accept

accept函数是为了接受来自客户端的连接请求的函数它是在三次握手之后发挥作用,这里也会有一些问题比如说accept发挥作用的时候此时并没有客户发送连接请求该怎么办呢?这里会陷入阻塞等待的状态也就是一直等到有连接请求为止。
connect()

客户端需要调用connect()连接服务器;
connect和bind的参数形式一致, 区别在于bind的参数是自己的地址, 而connect的参数是对方的地址;
connect()成功返回0,出错返回-1
封装TCP socket
tcp_socket.hpp
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <cassert>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
#define CHECK_RET(exp) if (!(exp)) {\return false;\
}
class TcpSocket {
public:TcpSocket() : fd_(-1) { }TcpSocket(int fd) : fd_(fd) { }bool Socket() {fd_ = socket(AF_INET, SOCK_STREAM, 0);if (fd_ < 0) {perror("socket");return false;}printf("open fd = %d\n", fd_);return true;}bool Close() const {close(fd_);printf("close fd = %d\n", fd_);return true;}bool Bind(const std::string& ip, uint16_t port) const {sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(ip.c_str());addr.sin_port = htons(port);int ret = bind(fd_, (sockaddr*)&addr, sizeof(addr));if (ret < 0) {perror("bind");return false;}return true;}bool Listen(int num) const {int ret = listen(fd_, num);if (ret < 0) {perror("listen");return false;}return true;}bool Accept(TcpSocket* peer, std::string* ip = NULL, uint16_t* port = NULL) const {sockaddr_in peer_addr;socklen_t len = sizeof(peer_addr);int new_sock = accept(fd_, (sockaddr*)&peer_addr, &len);if (new_sock < 0) {perror("accept");return false;}printf("accept fd = %d\n", new_sock);peer->fd_ = new_sock;if (ip != NULL) {*ip = inet_ntoa(peer_addr.sin_addr);}if (port != NULL) {*port = ntohs(peer_addr.sin_port);}return true;}bool Recv(std::string* buf) const {buf->clear();char tmp[1024 * 10] = {0};// [注意!] 这里的读并不算很严谨, 因为一次 recv 并不能保证把所有的数据都全部读完// 参考 man 手册 MSG_WAITALL 节. ssize_t read_size = recv(fd_, tmp, sizeof(tmp), 0);if (read_size < 0) {perror("recv");return false;}if (read_size == 0) {return false;}buf->assign(tmp, read_size);return true;}bool Send(const std::string& buf) const {ssize_t write_size = send(fd_, buf.data(), buf.size(), 0);if (write_size < 0) {perror("send");return false;}return true;}bool Connect(const std::string& ip, uint16_t port) const {sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(ip.c_str());addr.sin_port = htons(port);int ret = connect(fd_, (sockaddr*)&addr, sizeof(addr));if (ret < 0) {perror("connect");return false;}return true;}int GetFd() const {return fd_;}private:int fd_;
};
tcp_server.hpp
#pragma once
#include <functional>
#include "tcp_socket.hpp"
typedef std::function<void (const std::string& req, std::string* resp)> Handler;
class TcpServer {
public:TcpServer(const std::string& ip, uint16_t port) : ip_(ip), port_(port) {}bool Start(Handler handler) {// 1. 创建 socket;CHECK_RET(listen_sock_.Socket());// 2. 绑定端口号CHECK_RET(listen_sock_.Bind(ip_, port_));// 3. 进行监听CHECK_RET(listen_sock_.Listen(5));// 4. 进入事件循环for (;;) {// 5. 进行 acceptTcpSocket new_sock;std::string ip;uint16_t port = 0;if (!listen_sock_.Accept(&new_sock, &ip, &port)) {continue;}printf("[client %s:%d] connect!\n", ip.c_str(), port);// 6. 进行循环读写for (;;) {std::string req;// 7. 读取请求. 读取失败则结束循环bool ret = new_sock.Recv(&req);if (!ret) {printf("[client %s:%d] disconnect!\n", ip.c_str(), port);// [注意!] 需要关闭 socketnew_sock.Close();break;}// 8. 计算响应std::string resp;handler(req, &resp);// 9. 写回响应new_sock.Send(resp);
printf("[%s:%d] req: %s, resp: %s\n", ip.c_str(), port,req.c_str(), resp.c_str());}}return true;}
private:TcpSocket listen_sock_;std::string ip_;uint64_t port_;
};
我们开开心心的在一起
相关文章:
Linux——网络通信TCP通信常用的接口和tcp服务demo
文章目录 TCP通信所需要的套接字socket()bind()listen()acceptconnect() 封装TCP socket TCP通信所需要的套接字 socket() socket()函数主要作用是返回一个描述符,他的作用就是打开一个网络通讯端口,返回的这个描述符其实就可以理解为一个文件描述符&a…...
【web | CTF】反序列化打法
天命:因为是php的上古版本,所以本机无法复现,只能用归纳法解决,就是题海战术找相同点,fuzz来测试新的题目 题目一:绕过正则和绕过__wakeup函数,private属性 【web | CTF】攻防世界 Web_php_uns…...
如何在Linux搭建Inis网站,并发布至公网实现远程访问【内网穿透】
如何在Linux搭建Inis网站,并发布至公网实现远程访问【内网穿透】 前言1. Inis博客网站搭建1.1. Inis博客网站下载和安装1.2 Inis博客网站测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道(云端设置)2.3.…...
YOLOv9来了! 使用可编程梯度信息学习你想学的内容, v7作者新作!【文献速读】
YOLOv9文献速读,本文章使用 GPT 4.0 和 Ai PDF 工具完成。 文章地址:https://arxiv.org/pdf/2402.13616.pdf 文章目录 文章简介有哪些相关研究?如何归类?谁是这一课题在领域内值得关注的研究员?论文试图解决什么问题&a…...
【鸿蒙 HarmonyOS 4.0】网络请求
一、介绍 资料来自官网:文档中心 网络管理模块主要提供以下功能: HTTP数据请求:通过HTTP发起一个数据请求。WebSocket连接:使用WebSocket建立服务器与客户端的双向连接。Socket连接:通过Socket进行数据传输。 日常…...
QT中的多线程有什么作用?
概述 在学习QT线程的时候我们首先要知道的是QT的主线程,也叫GUI线程,意如其名,也就是我们程序的最主要的一个线程,主要负责初始化界面并监听事件循环,并根据事件处理做出界面上的反馈。但是当我们只限于在一个主线程上…...
redis最佳实践
原则:redis希望存储的是热点数据,尽量可以在一天内访问到。 最佳实践 选择合适的数据结构 redis有String、Hash、Set、SortedSet、List等结构,主要依据业务需要进行选择 string:几乎所有数据都可以用string存储,但是最好适用于…...
架构师技能9-深入mybatis:Creating a new SqlSession到查询语句耗时特别长
开篇语录:以架构师的能力标准去分析每个问题,过后由表及里分析问题的本质,复盘总结经验,并把总结内容记录下来。当你解决各种各样的问题,也就积累了丰富的解决问题的经验,解决问题的能力也将自然得到极大的…...
【JavaEE】_HTTP请求报头header
目录 1. Host 2. Content-Length与Content-Type 2.1 Content-Length 2.2 Content-Type 3. User-Agent(UA) 4. Referer 5. Cookie header的整体格式是“键值对”结构,一行是一个键值对,这些键值对都是HTTP定义好的、有特殊含…...
随想录刷题笔记 —二叉树篇10 450删除二叉搜索树节点 669修剪二叉搜索树 108有序数组转换为二叉搜索树
450删除二叉搜索树节点 删除结点分为2种情况: 1.结点的孩子只有一个或没有,则直接用孩子或空替代 2.结点的孩子有两个,用左孩子替代,将左孩子的右孩子移到结点右子树的最左结点 解法一:递归 class Solution {publ…...
Docker基础篇(二)
docker run -d docker run -d 容器名或容器ID docker run -d 后台生成容器,并退出容器(除容器中在运行脚本) docker run -it 交互生成容器 docker run -d centos /bin/sh -c “while true; do echo zen; sleep 2;done” 查看容器中的进程…...
时序数据库TimescaleDB,实战部署全攻略
📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…...
Gson 库的使用
Gson 是由 Google 开发的一个流行的 Java 库,用于处理 JSON 数据的序列化和反序列化。它提供了简单易用的 API,使得在 Java 应用程序中操作 JSON 数据变得非常方便。 以下是 Gson 库的一些主要特点和用法 简单易用 Gson 提供了一个简单而直观的 API,使得在 Java 应用程序中…...
Java Swing游戏开发学习1
不使用游戏引擎,只使用Java SDK开发游戏的学习。 游戏原理 图片来自RyiSnow视频讲解 原理结合实际代码 public class GamePanel extends Jpanel implements Runnable {...run(){}// 详情看下图... }项目结构 运行效果 代码code 在我的下载里面可以找到&#x…...
Stable Diffusion 模型的概念、类型、下载、安装、使用
本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 大家好,我是水滴~~ 我们在《Stable Diffusion WebUI 界面介绍》 时,第一个就讲到了 Stable Diffusion 模型,那么这个模型是什么?该从哪儿下载&…...
Go 1.22 对 net/http 包的路由增强功能详解
目录 方法匹配(Method Matching) 通配符(Wildcards) 路径前缀匹配 优先规则 兼容性 API 变更 小结 参考资料 Go 1.22 版本对 net/http 包的路由功能进行了增强,引入了方法匹配(method matching&…...
【安卓基础3】Activity(一)
🏆作者简介:|康有为| ,大四在读,目前在小米安卓实习,毕业入职 🏆本文收录于 安卓学习大全,欢迎关注 🏆安卓学习资料推荐: 视频:b站搜动脑学院 视频链接 &…...
SpringBoot基于JWT的token做登录认证
背景 我们在基于Session做登录认证的时候,会有一些问题,因为Session存储到服务器端,然后通过客户端的Cookie进行匹配,如果正确,则通过认证,否则不通过认证。这在简单的系统中可以这么使用,并且…...
[ 2024春节 Flink打卡 ] -- Paimon
2024,游子未归乡。工作需要,flink coding。觉知此事要躬行,未休,特记 Flink 社区希望能够将 Flink 的 Streaming 实时计算能力和 Lakehouse 新架构优势进一步结合,推出新一代的 Streaming Lakehouse 技术,…...
计算机网络——14CDN
CDN 视频流化服务和CDN:上下文 视频流量:占据着互连网大部分的带宽 Netflix,YouTube:占据37%,16%的下行流量 挑战:规模性-如何服务~1B用户? 单个超级服务器无法提供服务(为什么&am…...
OneNET物联网平台接入避坑指南:Android端用MQTTS协议请求数据,为什么你的Token总失效?
OneNET物联网平台MQTTS接入实战:Android端Token失效的深度排查与解决方案 第一次在Android应用中集成OneNET的MQTTS协议时,我盯着调试日志里反复出现的"401 Unauthorized"错误整整两天。官方文档看似清晰,但实际对接时才发现&…...
广东省内推荐靠谱的知识产权服务机构
在广东省,随着创新驱动发展战略的深入实施,知识产权的重要性日益凸显。无论是企业还是个人,都越来越重视知识产权的保护和运用。选择一家靠谱的知识产权服务机构至关重要,它能为客户提供专业、高效的服务,助力客户在知…...
避坑指南:RuoYi-Vue2集成Flowable 6.7.2时,关于database-schema-update和nullCatalogMeansCurrent的配置详解
深度解析:RuoYi-Vue2集成Flowable 6.7.2的数据库配置陷阱与实战策略 当企业级应用需要引入工作流引擎时,Flowable因其轻量化和高性能成为许多开发团队的首选。然而在RuoYi-Vue2框架中集成Flowable 6.7.2版本时,数据库配置环节往往成为开发者的…...
异构数据库迁移利器:dbswitch实现多源数据高效同步
1. 异构数据库迁移的痛点与常见方案 第一次接触异构数据库迁移时,我被各种工具搞得晕头转向。当时公司需要把Oracle的业务数据同步到Greenplum做分析,试了好几种方案都不太理想。比如用kettle配置gpload,光是理解那些参数就花了两天时间&…...
ColorControl开源显示调校工具:从新手到专家的HDR优化之路
ColorControl开源显示调校工具:从新手到专家的HDR优化之路 【免费下载链接】ColorControl Easily change NVIDIA display settings and/or control LG TVs 项目地址: https://gitcode.com/gh_mirrors/co/ColorControl 在数字显示技术快速发展的今天ÿ…...
granite-4.0-h-350m效果展示:Ollama运行下德语工业标准文档理解案例
granite-4.0-h-350m效果展示:Ollama运行下德语工业标准文档理解案例 1. 模型核心能力概览 Granite-4.0-H-350M是一个轻量级但功能强大的指令模型,专门针对设备部署和研究场景优化。这个350M参数的模型虽然体积小巧,但在多语言理解和指令跟随…...
【2026唯一认证流式部署标准】:FastAPI 2.0 + Uvicorn 24.8 + ASGI 4.0协同流控协议详解(含OpenTelemetry追踪模板)
第一章:FastAPI 2.0 异步 AI 流式响应的范式演进与2026标准定位FastAPI 2.0 将原生支持全链路异步流式响应(StreamingResponse)与 Server-Sent Events(SSE)语义融合,标志着 AI 应用后端从“请求-响应”单次…...
Simulink模型加密二选一:是选‘受保护模型’还是自己写S-Function?一份给嵌入式代码生成者的选择指南
Simulink模型加密实战:受保护模型与S-Function的深度技术选型 在嵌入式系统开发中,Simulink模型往往承载着核心算法和知识产权。当需要与团队协作或交付给客户时,如何在保证模型可用性的同时防止核心逻辑被窥探或篡改?这成为每个嵌…...
ECharts地图标注避坑指南:解决区域地图显示不全、标注错位等常见问题
ECharts地图标注避坑指南:解决区域地图显示不全、标注错位等常见问题 当你在使用ECharts绘制区域地图时,是否遇到过地图显示不全、标注点位置偏移、JSON数据格式错误等问题?这些问题看似简单,却可能耗费开发者大量时间排查。本文将…...
从零到一:基于NOAA HYSPLIT的后向轨迹实战绘制与污染溯源分析
1. 认识HYSPLIT与后向轨迹分析 第一次接触HYSPLIT模型时,我也被这个复杂的缩写搞得一头雾水。简单来说,这是美国国家海洋和大气管理局(NOAA)开发的一款专业大气轨迹分析工具,全称是Hybrid Single Particle Lagrangian …...
