做网站收款支付宝接口/网络营销的八大能力
目录
1、实现服务器的逻辑
1.1 socket
1.2 bind
1.3 listen
1.4 accept
1.5 read
1.6 write
1.7 服务器代码
2、实现客户端的逻辑
2.1 connect
2.3 客户端代码
3、实现服务器与客户端的通信
结语
前言:
在Linux下,实现传输层协议为TCP的套接字进行网络通信,网络层协议为IPv4,需要用到的接口如下:实现服务器的接口有(socket、bind、listen、accept、read、write),实现客户端的接口有(socket、connect、write、read)。
实现方式:因为网络通信的本质是进程间通信在云服务器上创建一个服务器进程和一个客户端进程,服务器进程先启动,然后让客户端链接到服务器上,至此客户端可以向服务器发送消息,并且服务器收到消息后可以给对方反馈信息。
TCP通信示意图如下:
1、实现服务器的逻辑
将服务器封装成一个类,服务器的端口号、IP地址以及网络描述符(一种类似文件描述符的字段)作为类的成员变量,这样做的好处是对软件实现分层,方便维护代码。按照下文的接口顺序调用实现服务器类。
1.1 socket
实现网络通信的第一步基本都是调用socket接口,目前已经明确传输层协议为TCP,网络层协议为IPv4,因此可以直接调用socket,该函数介绍如下:
#include <sys/types.h>
#include <sys/socket.h>int socket(int domain, int type, int protocol);
//domain表示网络层协议,填AF_INET表示IPv4,填AF_INET6表示IPv6
//type表示传输层协议,SOCK_STREAM为TCP,SOCK_DGRAM为UDP
//protocol表示指定特定的协议,默认填0即可//调用成功返回一个类型文件描述符的网络描述符,失败返回-1
1.2 bind
在网络通信中,bind函数与socket函数密不可分,他是用来绑定网络描述符和地址信息的,目的是让后续的通信可以直接通过网络描述符进行。在使用bind函数前,需要先创建一个包含地址信息的结构体,IPv4对应的结构体类型是struct sockaddr_in,该结构体里需要程序员手动填写3个信息,分别是:1、TCP/UDP,2、自定义的端口号,3、该主机的IP地址。
体现地址信息的伪代码如下:
struct sockaddr_in local;//定义变量
memset(&local, 0, sizeof(local));//对内部内容清零
local.sin_family = AF_INET;//填写ip协议
local.sin_port = htons(port_);//填写端口号
inet_aton(ip_.c_str(), &(local.sin_addr));//填写ip地址
其中由于网络传输数据规定以大端字节序传输,因此填写端口号和ip时需要对其进行大端字节序的转换,这里可以调用htons函数和inet_aton函数实现转换,这两个函数的介绍如下:
#include <arpa/inet.h>
uint16_t htons(uint16_t hostshort);
//将主机字节序转换成网络大端字节序,以返回值的形式转换#include <arpa/inet.h>
int inet_aton(const char *string, struct in_addr*addr);
//将字符串形式的ip转换成网络字节序,并直接赋值给addr指向的空间
在地址信息完善后,紧接着就是调用bind函数进行绑定,bind函数介绍如下:
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
//socket表示要绑定的网络描述符
//address表示指向的地址信息变量
//address_len表示地址信息变量的大小//调用成功返回0,失败返回-1并设置错误码
1.3 listen
与UDP不同的是,UDP绑定之后就可以用网络描述符进行接收和发送消息的操作了,但是TCP不一样,TCP的绑定完成后需要对网络描述符再进行监听操作,监听实际上是一种抽象的连接概念(因为TCP是有连接的,而UDP是无连接的,所以需要监听),即调用listen函数。listen函数的介绍如下:
#include <sys/socket.h> int listen(int sockfd, int backlog);
//sockfd表示要监听的网络描述符
//backlog表示设置套接字的链接队列的最大数量//调用成功返回0,失败返回-1并设置错误码
1.4 accept
待上述3个函数完成基础工作后,接下来就是最重要的连接环节了,accept函数的作用是和客户端进行连接,但是注意链接不意味着直接接收对方发来的数据,连接完成之后才能开始正常通信。accept函数介绍如下:
#include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//sockfd表示服务器的网络描述符,即通过观察该描述符得知是否有客户端链接
//addr是指向地址信息的指针,用来保存客户端的地址信息
//addrlen表示存储客户端地址信息的结构体大小//重要的是调用成功时返回一个新的网络描述符,失败返回-1
accept的重要之处在于若连接成功,则返回一个新的网络描述符,而该网络描述符才是后续通信的”端口“,意味着现在服务器有两个网络描述符了,一个是socket返回的,一个是accept返回的。可以这样理解他们:socket返回的描述符表示该服务器的总描述符,类似二叉树的根结点,而accept返回的描述符就是用于服务多个客户端的次描述符,即给每个来连接的客户端都分配一个次描述符,类似二叉树的叶子结点。(但是当前服务器的实现只能服务单客户端,因为他不是多线程的)
题外话:UDP通信只有一个网络描述符,所有的客户端都是通过这一个描述符来进行和服务器的通信。
1.5 read
链接完毕之后,说明此时客户端和服务器双方建立了联系,服务器的下一步就是读取客户端发送的信息,因为TCP是面向字节流的,因此可以使用文件操作的方式进行流读取,即使用read函数读取客户端发送的数据,read函数介绍如下:
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);
//fd表示要读取的文件描述符
//buf表示将读取数据存放至缓冲区的缓冲区指针
//count表示读取的字节数
1.6 write
服务器不仅仅可以接收数据,还可以向客户端反馈数据,因为accept让服务器和客户端之间有了唯一的网络描述符,因此服务器可以通过该描述符对客户端反馈信息,而无需像UDP需要记录对方的地址信息才可以反馈信息。write函数介绍如下:
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);
//fd表示要写入的文件描述符
//buf表示指向写入的内容
//count表示要写入的字节
1.7 服务器代码
实现服务器类的代码如下:
#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";//云服务器默认通信ip
const int backlog = 10; // 但是一般不要设置的太大class TcpServer
{
public:TcpServer(const uint16_t &port, const std::string &ip = defaultip) : listensock_(defaultfd), port_(port), ip_(ip){}void InitServer(){listensock_ = socket(AF_INET, SOCK_STREAM, 0);printf("创建套接字成功, listensock_: %d\n", listensock_);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));bind(listensock_, (struct sockaddr *)&local, sizeof(local));printf("绑定套接字成功, listensock_: %d\n", listensock_);// Tcp是面向连接的,服务器一般是比较“被动的”,//服务器一直处于一种,一直在等待连接到来的状态listen(listensock_, backlog);printf("监听套接字成功, listensock_: %d\n", listensock_);}void Start(){printf("TCP服务器正在运行....");for (;;){// 1. 获取新连接struct sockaddr_in client;//保存客户端的地址信息socklen_t len = sizeof(client);//类似recvfromint sockfd = accept(listensock_, (struct sockaddr *)&client, &len);uint16_t clientport = ntohs(client.sin_port);//将客户端端口号拿出来char clientip[32];//将ip从网络字节序转换成主机序列并写进缓冲区clientip内inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));printf("链接到一个客户端, sockfd: %d, client port: %d\n", sockfd, clientport);// 2. 根据新连接来进行通信Service(sockfd);close(sockfd);//关闭文件描述符}}void Service(int sockfd){// 测试代码char buffer[4096];while (true){ssize_t n = read(sockfd, buffer, sizeof(buffer));if (n > 0){buffer[n] = 0;std::cout << "客户端说# " << buffer << std::endl;std::string echo_string = "服务器回答# ";echo_string += buffer;write(sockfd, echo_string.c_str(), echo_string.size());}else if(n==0){std::cout<<"读到文件末尾"<<std::endl;sleep(1);break;}else{std::cout<<"读到出错"<<std::endl;sleep(1);break;}}}~TcpServer() {if(listensock_>0) close(listensock_);}private:int listensock_;uint16_t port_;std::string ip_;
};
2、实现客户端的逻辑
与服务器相比,客户端的实现逻辑要简单许多,因为服务器要将底层的基础设施建设好,而客户端只需要完成连接这一个动作即可,然后就是发送数据和接收反馈,当然,客户端的第一步也是调用socket拿到属于客户端的网络描述符,因为后续的通信工作要通过该描述符进行。
2.1 connect
客户端只需要做连接动作即可,而连接动作是依靠connect函数实现的,connect函数介绍如下:
#include <sys/types.h>
#include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//sockfd表示要与对方建立连接的客户端网络描述符
//addr指向地址信息的地址,该地址信息即服务器的地址信息
//addrlen表示addr指向的地址信息的大小
所以调用connect前必须知道服务器的地址信息:即ip地址和端口号,可以通过命令行参数的形式传给客户端代码,并且拿到地址信息后也是要构造struct sockaddr_in变量将信息填写进去。
2.3 客户端代码
实现客户端代码如下(注意客户端直接在main函数中实现,无需在对其进行封装,因为客户端的代码简单):
#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\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}// ./tcpclient serverip serverport
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}//从命令行参数获取服务器的端口和ipstd::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);// 将ip转换成网络字节序inet_pton(AF_INET, serverip.c_str(), &(server.sin_addr)); int sockfd = 0;sockfd = socket(AF_INET, SOCK_STREAM, 0);//创建套接字// 客户端发起connect的时候,进行自动随机bind//链接服务器int n = connect(sockfd, (struct sockaddr *)&server, sizeof(server));if (n < 0){std::cout << "链接失败, reconnect: " << std::endl;sleep(2);}while (true){std::string message;std::cout << "Please Enter# ";std::getline(std::cin, message);int n = write(sockfd, message.c_str(), message.size());//发送数据if (n < 0){std::cout << "write出错" << std::endl;// break;}char inbuffer[4096];n = read(sockfd, inbuffer, sizeof(inbuffer));//接收反馈if (n > 0){inbuffer[n] = 0;std::cout << inbuffer << std::endl;}}close(sockfd);return 0;
}
3、实现服务器与客户端的通信
实现双方通信前,必须满足双方都为进程,但是服务器目前还只是一个类,因此要把服务器类实例化在main函数中,让服务器也变成进程。实现服务器进程的代码如下:
#include "TCPser.hpp"
#include <iostream>
#include <memory>void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " port[1024+]\n" << std::endl;
}// 下节课:守护进程化
int main(int argc, char *argv[])
{if(argc != 2){Usage(argv[0]);exit(1);}uint16_t port = std::stoi(argv[1]);std::unique_ptr<TcpServer> tcp_svr(new TcpServer(port));tcp_svr->InitServer();tcp_svr->Start();return 0;
}
运行结果:
特别注意:通信时,必须保证服务器先运行起来,若客户端先运行起来,则会在connect处连接失败,因为找不到对应的服务器端口号。
结语
以上就是关于在Linux下实现TCP网络通信的讲解,实现TCP的主要思路是了解套接字的作用,以及理清对套接字相关函数的调用顺序,并且其次TCP通信的原理。
最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!
相关文章:

Linux_实现TCP网络通信
目录 1、实现服务器的逻辑 1.1 socket 1.2 bind 1.3 listen 1.4 accept 1.5 read 1.6 write 1.7 服务器代码 2、实现客户端的逻辑 2.1 connect 2.3 客户端代码 3、实现服务器与客户端的通信 结语 前言: 在Linux下,实现传输层协议为TCP…...

正则表达式与文本三剑客之grep
目录 前言 一、grep命令 二、基础正则表达式常见元字符 2.1、特殊字符 2.2、定位符 2.3、非打印字符 三、元字符操作实例 3.1、查找特定字符 3.2、利用中括号“[]”来查找集合字符 3.3、查找行首“^”与行尾字符“$” 3.4、查找任意一个字符“.”与重复字符“*” 3.…...

微信小程序开发:项目程序代码构成
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...

【云原生】Kubernetes微服务Istio:介绍、原理、应用及实战案例
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

【Docker】Docker-consul容器服务自动发现与注册
目录 一.Consul概述 1.解决了什么问题 2.什么叫微服务或者注册与发现 3.consul的模式 4.相关命令 二.consul 部署 1.consul服务器部署 2.部署docker容器 3.Nginx负载均衡器 3.1.安装启动nginx 3.2.配置nginx负载均衡 3.3.创建配置consul complate模板文件 3.4.添加…...

Go 1.22 remote error: tls: handshake failure
Golang 1.22 remote error: tls: handshake failure 1.22之前运行下面代码是没有错误 package mainimport ("crypto/tls""fmt""net/http" )func main() {http.DefaultTransport.(*http.Transport).TLSClientConfig &tls.Config{InsecureS…...

迈向通用人工智能:AGI的到来与社会变革展望
正文: 随着科技的飞速发展,通用人工智能(AGI)的来临似乎已不再遥远。近期,多位行业领袖和专家纷纷预测,AGI的到来时间可能比我们想象的要早。在这篇博客中,我们将探讨AGI的发展趋势、潜在影响以…...

大模型额外篇章三:vercel搭建openai中转服务器
文章目录 一、起因和注意1)起因2)注意二、实现方法(原理:透传)1)nginx方案2)node服务3)纯 js 方案4)选择国外的域名服务商(DNS 解析路径缩短,建议方案国外提供 CDN 云服务商结合自建云服务业务做负载均衡)三、实践(vercel部署OpenAI代理服务器)四、测试搭建的Ope…...

使用 jQuery 中的 this 实例
在 jQuery 中,this 关键字用于表示指向当前操作的 DOM 元素。本篇博客将详细介绍如何在 jQuery 中使用 this 实例。 一、选择器中的 this 在选择器中,this 可以方便地指向当前操作的 DOM 元素。例如,当用户点击一个按钮时,我们想…...

下载最新版Anaconda、安装、更换源、配置虚拟环境并在vscode中使用
文章目录 进入官网进入下载页安装更换源配置虚拟环境env安装包requests在vscode中使用虚拟环境 进入官网 https://repo.anaconda.com/ 或进入清华大学下载 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 进入下载页 安装 更换源 查看已经存在的镜像源 bash cond…...

极狐GitLab Git LFS(大文件存储)如何管理?
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab :https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署…...

迭代学习笔记
一、迭代学习定义和分类 1、直观理解 迭代学习一般应用于重复性的场景。比如控制一个单自由度的小车以特定的速度曲线移动到指定位置,整个时间是10s,控制频率是0.01,那么整个控制序列就会有1000个点。这1000个点在10s内依次发出,…...

【安全】系统安全设计规范(DOC完整版)
1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 软件资料清单列表部分文档&…...

windows常用命令整理
本文分享一些常用的windows命令。根据功能的不同,大致可分为以下几个方面,一是文件操作命令,二是进程相关命令,三是磁盘相关命令,四是网络相关命令,五是其他命令。 1.文件操作命令 dir:显示当…...

视频处理基础知识1
1、图像基本知识 图像的组成:像素、RGB(每个像素由三个发光二极管组成)、分辨率(横纵向像素的个数乘积) PPI每英寸的像素数 DPI每英寸的点数,有可能一个点有多个像素 PPI>300 就属于视网膜级别,就是很清晰&#…...

Linux退不出vim编辑模式
目录 第一章、问题分析1.1)报错提示 第二章、解决方式 友情提醒: 先看文章目录,大致了解文章知识点结构,点击文章目录可直接跳转到文章指定位置。 第一章、问题分析 1.1)报错提示 报错如下:使用Linux的vi…...

TikTok养号的网络环境及相关代理IP知识
TikTok作为一个流行的短视频分享平台,其用户量非常庞大,很多商家和个人都会使用TikTok来进行引流和推广。由于TikTok的规则和政策限制了每个用户每天发布视频的数量,因此许多用户会使用多个账号来发布更多的视频以提高曝光率。 然而ÿ…...

过程调用和数组的分配访问
系列文章 : 深入理解计算机系统笔记 文章目录 系列文章3.7 过程3.7.1 运行时栈3.7.2 转移控制3.7.3 数据传送3.7.4 栈上的局部存储3.7.5 寄存器中的局部存储空间3.7.6 递归过程 3.8 数组分配和访问3.8.1 基本原则3.8.2 指针运算3.8.3 嵌套的数组3.8.4 定长数组3.8.5 变长数组…...

TeamViewer手机端APP提示:请先验证账户
当你在手机端下载安装了TeamViewerAPP后,需要你先登录个人账号,然后还会要求你验证账户,同时跳转到一个网址中,但是这个网址并没有自动跳转到验证账户的位置。 解决办法: 在手机浏览器中进入下面这个网址:…...

【SpringBoot】分页查询
1. Controller ApiOperation("分页查询")GetMapping("/page")public Result<PageResult> pageResultResult(EmployeePageQueryDTO employeePageQueryDTO) {System.out.println(employeePageQueryDTO.toString());PageResult pageResult employeeSer…...

微软CrowdStrike驱动蓝屏以及内核签名
原因 当Windows操作系统遇到严重错误导致系统崩溃时,屏幕显示为蓝色,通常伴有错误代码和信息,这被称为“蓝屏死机”(Blue Screen of Death,简称BSOD) https://www.thepaper.cn/newsDetail_forward_281262…...

Spring中Bean的循环依赖
目录 定义: 循环依赖的后果: 一:三级缓存 1、大概的思路: 注意: 2、执行过程: A半完成: B完成: A完成: 注: 二:Lazy 定义: …...

Java二十三种设计模式-代理模式模式(8/23)
代理模式:为对象访问提供灵活的控制 引言 代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一个代替或占位符,以控制对它的访问。 基础知识,java设计模式总体来说设计模式分为三大类&#…...

Windows 11 家庭中文版 安装 VMWare 报 安装程序检测到主机启用了Hyper-V或Device
1、问题 我的操作系统信息如下: 我在安装 VMWare 的时候,报: 因为我之前安装了 docker 桌面版,所以才报这个提示。 安装程序检测到主机启用了 Hyper-v或 Device/credential Guard。要在启用了Hyper-或 Device/Credential Guard …...

机械学习—零基础学习日志(高数09——函数图形)
零基础为了学人工智能,真的开始复习高数 函数图像,开始新的学习! 幂函数 利用函数的性质,以幂函数为例,因为单调性相同,利用图中的2和3公式,求最值问题,可以直接将式子进行简化。这…...

java迭代集合出现并发修改异常(ConcurrentModificationException)的原因以及解决方案
java迭代集合出现并发修改异常(ConcurrentModificationException)的原因以及解决方案 一. 什么时候会出现并发修改异常? 这里先看需求 : 定义一个集合,存储 唐僧,孙悟空,猪八戒,沙僧,遍历集合,如果遍历到猪八戒,往集合中添加一个白龙马 很显然要求我们先创建一个集合并进行…...

BGP选路之Local Preference
原理概述 当一台BGP路由器中存在多条去往同一目标网络的BGP路由时,BGP协议会对这些BGP路由的属性进行比较,以确定去往该目标网络的最优BGP路由。BGP首先比较的是路由信息的首选值(PrefVal),如果 PrefVal相同,就会比较本…...

WEB渗透信息收集篇--IP和端口信息
WEB渗透信息收集篇--域名信息-CSDN博客 WEB渗透信息收集篇--网站架构和指纹识别-CSDN博客 WEB渗透信息收集篇--人员信息-CSDN博客 WEB渗透信息收集篇--其他信息-CSDN博客 一、ASN ASN Tool - MxToolBox ASN通常指的是"自…...

国内微短剧系统平台抖音微信付费小程序app开发源代码交付
微短剧作为当下热门的内容,结合抖音平台的广泛用户基础,开发微短剧付费小程序APP具有显著的市场潜力,用户对于短剧内容的需求旺盛,特别是在言情、总裁、赘婿等热门题材方面,接下来给大家普及一下微短剧小程序系统。 顺…...

Java语言程序设计基础篇_编程练习题**15.19 (游戏:手眼协调)
**15.19 (游戏:手眼协调) 请编写一个程序,显示一个半径为10像素的实心圆,该圆放置在面板上的随机位置,并填充随机的顔色,如图15-29b所示。单击这个圆时,它会消失,然后在另一个随机的位置显示新的随机颜色的…...