Socket编程模型

一、整体过程图解

                 

二、Socket编程模型细节

        客户端和服务器能在网络中通信,那必须得使用Socket编程,它是进程间通信里比较特别的方式,特别之处在于它是可以跨主机间通信。
创建Socket 的时候,可以指定网络层使用的是IPv4还是IPv6,传输层使用的是TCP还是UDP。服务器的程序要先跑起来,然后等待客户端的连接和数据,我们先来看看服务端的Socket编程过程是怎样的。
服务端首先调用socket()函数,创建网络协议为IPv4,以及传输协议为TCP的Socket。

接着调用bind()函数,给这个Socket绑定一个IP地址和端口,绑定这两个的目的是什么?

  • 绑定端口的目的:当内核收到TCP报文,通过TCP头里面的端口号,来找到我们的应用程序,然后把数据传递给我们。
  • 绑定IP地址的目的:一台机器是可以有多个网卡的,每个网卡都有对应的IP地址,当绑定一个网卡时,内核在收到该网卡上的包,才会发给我们;

绑定完IP地址和端口后,就可以调用listen()函数进行监听,此时对应TCP状态图中的listen,如果我们要判定服务器中一个网络程序有没有启动,可以通过netstat命令查看对应的端口号是否有被监听。


服务端进入了监听状态后,通过调用accept()函数,来从内核获取客户端的连接,如果没有客户端连接,则会阻塞等待客户端连接的到来。


那客户端是怎么发起连接的呢?客户端在创建好Socket后,调用connect()函数发起连接,该函数的参数要指明服务端的IP地址和端口号,然后万众期待的TCP三次握手就开始了。
在TCP连接的过程中,服务器的内核实际上为每个Socket维护了两个队列:

  • 一个是「还没完全建立」连接的队列,称为TCP半连接队列,这个队列都是没有完成三次握手的连接,此时服务端处于syn_rcvd 的状态;
  • 一个是「已经建立」连接的队列,称为TCP全连接队列,这个队列都是完成了三次握手的连接,此时服务端处于established 状态;

当TCP全连接队列不为空后,服务端的accept()函数,就会从内核中的TCP全连接队列里拿出一个已经完成连接的Socket返回应用程序,后续数据传输都用这个Socket。
注意,监听的Socket和真正用来传数据的Socket是两个:

  • 一个叫作监听Socket;
  • 一个叫作已连接Socket;

连接建立后,客户端和服务端就开始相互传输数据了,双方都可以通过read()和write()函数来读写数据。

三、服务端、客户端代码供参考

服务器代码:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/socket.h>
#include<netinet/ip.h>
#include<arpa/inet.h> #define SERROPT 8000
#define SERIP "192.168.111.110"
int main(int argc, char* argv[])                                                                                                                                               
{//创建一个套接字 socket参数1.协议类型 2.流式套接字 3.传0(默认TCP协议)int lfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in seraddr, cliaddr;seraddr.sin_family = AF_INET;seraddr.sin_port = htons(SERROPT);       //8000->16415seraddr.sin_addr.s_addr=INADDR_ANY;//seraddr.sin_addr.s_addr = 2171971776;  //192.168.117.129->2171971776//inet_pton(AF_INET, SERIP ,(void*)&seraddr.sin_addr.s_addr);//本地ip转网络ip函数//参数1.要绑定文件描述符 2.结构体包括(协议类型、端口号、地址)3.长度bind (lfd, (struct sockaddr*)&seraddr, sizeof(seraddr));listen(lfd,64);//socklen_t clilen = sizeof(cliaddr);int cfd = accept(lfd , (struct sockaddr*)&cliaddr, &clilen);//第三个套接字 //accept是在全连接队列中取出连接 如果多次连接 全连接里没有连接可用 会发生阻塞char buf[1024];while(1){int rr = read(cfd, buf, sizeof(buf));//读 读缓冲write(STDERR_FILENO, buf, rr);   //写到标准输出上write(cfd, buf, rr); //反射回去证明客户端已经接收到了}return 0;      
} 

客户端代码:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<sys/socket.h>
#include<netinet/ip.h>
#include<arpa/inet.h> #define SERROPT 8000
#define SERIP "192.168.111.110"
#define CLIPORT 8001
#define CLIIP "192.168.111.110" 
int main(int argc, char* argv[])                                                                                                                                               
{//创建一个套接字 int cfd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in seraddr, cliaddr;   //定义两个结构体cliaddr.sin_family = AF_INET;cliaddr.sin_port = htons(CLIPORT);      inet_pton(AF_INET, CLIIP ,(void*)&cliaddr.sin_addr.s_addr);bind (cfd, (struct sockaddr*)&cliaddr, sizeof(cliaddr));  //客户端绑定//seraddr.sin_family = AF_INET;seraddr.sin_port = htons(SERROPT);       inet_pton(AF_INET, SERIP ,(void*)&seraddr.sin_addr.s_addr);connect(cfd, (struct sockaddr*)&seraddr, sizeof(seraddr));//连接char buf[1024];while(1){int rr = read(0, buf, sizeof(buf)); //等待输入write(cfd, buf, rr);  rr = read(cfd, buf, sizeof(buf));write(1, buf, rr); //反射回去证明已经接收到了}return 0;      
} 

        端口随便设定合理就行,IP地址(我这里随便写的IP)查看自己虚拟机IP(通过命令:ifconfig)查看,不要忘记更改,先启动服务器、再启动客户端,这样一个简单的Socket编程模型就搭建好了。

        基于Linux一切皆文件的理念,在内核中Socket也是以「文件」的形式存在的,也是有对应的文件描述符。

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

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

相关文章

jvm必知必会-类的生命周期图文详解

类的生命周期描述了一个从加载、使用到卸载的过程; 而其中的 连接 部分又分为一下三个阶段: 验证准备解析6.1 加载阶段 Loading阶段第一步是 类加载器 会根据类全限定名通过不同的渠道以二进制流的方式获取字节码信息,程序员可以使用Java代码扩展不同的渠道。 比如通过 …

LeetCode 算法:螺旋矩阵c++

原题链接&#x1f517;&#xff1a;螺旋矩阵 难度&#xff1a;中等⭐️⭐️ 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&…

实用技巧:跳过TCODE权限检查ALINK_CALL_TRANSACTION

RFC&#xff1a;ALINK_CALL_TRANSACTION 遇到tcode 提示没有权限打开&#xff0c;可以通过这个RFC,debug 修改检查值&#xff0c;打开TCODE。 适用于紧急情况 断点打在20行&#xff0c;SY-SUBRC 的值改成 1

【ARMv8/ARMv9 硬件加速系列 3.4 -- SVE 复制指令CPY 使用介绍】

文章目录 SVE 复制指令CPYSVE 指令格式SVE 使用语法SVE CPY 使用示例SVE CPY 小结SVE 复制指令CPY CPY <Zd>.<T>, <Pg>/M, #<imm>{, <shift>}cpy 指令在 ARMv9 的

MySQL的卸载

先停止对应MySQL服务&#xff0c;然后再进行删除&#xff08;进入MySQL安装目录bin目录内以管理员身份打开命令行&#xff09; 停止服务 net stop Mysql&#xff08;服务名&#xff09; ——MySQL&#xff08;服务名&#xff09;安装时是什么名字就写什么名字 卸载 mysqld …

在矩池云快速使用ChatTTS,文本转语音太酷了

ChatTTS 最新的一款文本转语音模型&#xff0c;目前支持英文和中文两种语言&#xff0c;面向对话场景的转化则更为精准&#xff0c;在汉语的语音韵律方面超越了以往很多同类模型&#xff0c;此外它还支持细粒度控制&#xff0c;允许在文字中加入笑声、停顿、语气词等&#xff0…

不会策划营销活动?教你一步步成为策划高手

要想让活动大获成功&#xff0c;不仅需要创意十足&#xff0c;更要有严谨的策划和执行&#xff0c;确实新人会有点感觉不知所措。 但其实也不用怕&#xff0c;只要按照以下五个关键步骤&#xff0c;一步步来&#xff0c;也可以轻松策划及格的好活动。 步骤一&#xff1a;锁定目…

建筑垃圾/城市固废倾倒转移乱象:EasyCVR+AI智能视频监控方案助力城市环保监管

近日有新闻记者报道&#xff0c;中央生态环境保护督察组在上海、浙江、江西、湖北、湖南、重庆、云南7省市督察发现&#xff0c;一些地方建筑垃圾处置工作存在明显短板&#xff0c;乱堆乱倒问题时有发生&#xff0c;比如&#xff0c;江西湘东区在杨家田地块违规设置弃土场&…

Confluence安装

Confluence安装 1.安装 #下载confluence版本&#xff08;8.5.11&#xff09; https://www.atlassian.com/software/confluence/download-archives #修改权限 chmod x atlassian-confluence-8.5.11-x64.bin #执行安装 ./atlassian-confluence-8.5.11-x64.bin按照以下提示输入&…

WebGIS如何加载微件

本篇文章以加载切换底图微件做示范 首先&#xff0c;添加require "esri/widgets/ScaleBar",//比例尺"esri/widgets/Legend",//图例"esri/widgets/basemapGallery" 然后添加加载切换底图的组件代码 const basemapGallery new BasemapGallery(…

【乳业巨擘·数字革命先锋】光明乳业:上市公司科技蜕变,搭贝低代码引领未来新纪元

在这个由科技编织的未来世界里&#xff0c;光明乳业股份有限公司以巨人之姿&#xff0c;傲立于乳业之巅&#xff0c;以其无与伦比的胆识与魄力&#xff0c;引领了一场震撼业界的数字化革命。与低代码领域的创新领袖——搭贝的强强联合&#xff0c;不仅标志着光明乳业在数字化转…

DBeaver连接数据库

1、空白处右键点击 2、创建-连接 3、选择不同的数据库 4、修改信息 (mac)双击&#xff0c;连接&#xff0c;根据自己的需求重命名

jeecg快速启动(附带本地运行可用版本下载)

版本整理&#xff08;windows x64位&#xff09;&#xff1a; redis&#xff1a;3.0.504 MYSQL&#xff1a;5.7 Maven&#xff1a;3.9.4(setting文件可下载) Nodejs&#xff1a;v16.20.2&#xff08;建议不要安装默认路径下&#xff0c;如已安装在c盘&#xff0c;运行yarn报…

SAP 在过账的时候系统提示:被合并的公司 XXXX 和 ‘ ‘ 是不同的解决办法

最近用户反馈在STO的业务模式中交货单过账的时候&#xff0c;报错没有办法过账。查看了一下报错的信息提示&#xff1a;被合并的公司 和1300是不同的 如下图所示&#xff1a; 消息号是F5080 首先根据SAP的消息号找了一下NOTE&#xff0c;发现2091823有详细的说。 主要是财务…

准备好迎接3D世界的AI革新了吗:Direct3D,让3D创作触手可及

DreamTech 推出原生 3D-DiT 大模型 Direct3D 前言 3D-DiT大模型Direct3D 就目前的AI市场而言&#xff0c;将文本和图像转化为高质量的3D资产一直很难实现&#xff0c;主要目前缺乏一种能够捕捉复杂几何结构而且还能够扩展的3D的方法。但 DreamTech 发布了一种名为Direct3D的新型…

网络安全 DVWA通关指南 SQL Injection(SQL注入)

DVWA SQL Injection 文章目录 DVWA SQL InjectionLowMediumHighImpossible SQL注入漏洞基本原理 Web应用程序对用户输入的数据校验处理不严或者根本没有校验&#xff0c;致使用户可以拼接执行SQL命令。 可能导致数据泄露或数据破坏&#xff0c;缺乏可审计性&#xff0c;甚至导致…

做恒指交易一定要有耐心

1、记住成为赢利的交易者是一个旅程&#xff0c;而非目的地。世界上并不存在只赢不输的交易者。试着每天交易的更好一些&#xff0c;从自己的进步中得到乐趣。聚精会神学习技术分析的技艺&#xff0c;提高自己的交易技巧&#xff0c;而不是仅仅把注意力放在自己交易输赢多少上。…

vite配置之获取.env.[mode]下的数据

需求 vite.config.ts获取配置文件下面的数据.vue,.ts,.tsxsrc文件夹下面获取配置文件下面的数据 一、src/* .vue,.ts,.tsx 文件夹下面使用环境变量 之前webpack或者用的vue-cli我们在获取配置文件数据的时候通过process.env&#xff0c;但是在vite里面不能通过这种方式 vit…

Redis作者长文总结LLMs, 能够取代99%的程序员

引言 这篇文章并不是对大型语言模型&#xff08;LLMs&#xff09;的全面回顾。很明显&#xff0c;2023年对人工智能而言是特别的一年&#xff0c;但再次强调这一点似乎毫无意义。相反&#xff0c;这篇文章旨在作为一个程序员个人的见证。自从ChatGPT问世&#xff0c;以及后来使…

保姆级pycharm远程连接linux服务器

1、登录服务器&#xff0c;创建账号。 一般都是管理员账户登录&#xff0c;创建自己的账号。如果不需要&#xff0c;可跳过这步。 打开MobaXterm&#xff0c;点击左上角Session创建会话。 再点击左上角SSH&#xff0c;分别输入服务器ip和账号&#xff0c;最后点ok&#xff0c;进…