<计算机网络自顶向下> TCPUDP套接字编程

应用实现:源端的应用进程交换报文实现应用协议,来实现各种各样的网络应用(dash,email,  etc)

而应用层通信不可以直接通信,需要借助下层的服务才可以进行,通过层间接口交给下层,通过下层的服务传输

传输层在TCP/IP提供的就是socket API服务,传输报文之前建立socket,借助于socket收发,使用完成了以后关掉(socket就像一个门,接和收都一样)

两种socket类型:

  • TCP:可靠的,字节流/管道(报文之间没有边界)服务
  • UDP:不可靠(数据UDP数据包)服务

TCP套接字编程 

  • 服务器首先运行,等待连接建立

1. 创建欢迎socket:目的是返回一个整数(这个整数就是welcome soket,但没什么具体含义)

2. 将这个创建的整数和本地端口捆绑

3. 在欢迎socket上阻塞式等待接受用户的连接 (调用accept函数,如果没连接就阻塞,反之接受连接)

总的来说:创建——捆绑——等待

  •  客户端主动和服务器建立连接

    1. 创建客户端本地套接字(隐式捆绑到本地端口,就是默认与当前没用的端口捆绑)

    2. 调用connect阻塞连接指定服务器进程的IP地址和端口号

  •  当与客户端连接请求到来时
    1. 服务器接受来自用户端的请求,解除阻塞式等待,返回一个新的sockket值(同时与服务端和客户端捆绑,这个是connection socket)
  •  连接API调用有效时,客户端与服务器建立了TCP链接

  数据结构 sockaddr_in

  • 作用:指定网络操作的目标地址(设置网络进程和端口号)
  • 不仅仅可以用于IP通信,还可以用于IPX通信。所以要给一个常量说明使用在哪个通信的
  • IP地址和port捆绑关系的数据结构(标示进程的端节点)
  • 这个结构体用于存储 IP 地址。它包含了一个地址族(通常是 AF_INET,表示 IPv4),一个端口号和一个 IP 地址。当你创建一个套接字并想要连接到一个特定的 IP 地址和端口号时,你需要设置一个 struct sockaddr_in 结构体,并将它传递给 connect 或 bind 函数
//IP地址和port捆绑关系的数据结构(标示进程的端节点)
struct sockaddr_in{short sin_family;    //AF_INET u_short sin_port;   // portstruct in_addrsin_addr; 
//  IP address, unsigned longchar sin_zero[8]; // align}; 

数据结构 host_ent

  • 作用:获取主机信息(IP地址)
  • 更清晰的表述:struct hostent:这个结构体用于存储主机的信息,如主机名、别名、地址类型、地址长度和地址列表。当你调用 gethostbyname 函数时,它会返回一个指向 struct hostent 类型的指针。这个结构体包含了你所查询的主机的信息。例如,如果你查询的是一个域名,那么 gethostbyname 函数会返回这个域名对应的 IP 地址
  • 包括
    • *h_name:主机域名的指针
    • **h_aliases:主机的一系列别名,二级指针
    • h_length:地址长度
    • 第四个是IP地址的列表,二级指针
      //域名和IP地址的数据结构
      struct hostent{ char *h_name; 
      char **h_aliases; 
      int h_addrtype; 
      int h_length; /*地址长度*/ 
      char **h_addr_list; 
      #define h_addr h_addr_list[0];} 
      //作为调用域名解析函数时的参数
      //返回后,将IP地址拷贝到sockaddr_in的IP地址部分

C/S socket交互:TCP

代码示例

  • 客户端

也就是说这个sockaddr实际存储的是即将连接的服务器信息以及联机方式,而gethostbyname实际上是提供映射函数,只要输出服务器端口号就可以得到一个hostent指针然后用箭头函数得出需要的信息比如IP地址等等然后copy到socketaddr。

注意!这里socket是隐式的绑定了本地可用端口,没有显示调用bind函数

/*client.c*/ 
void main(int argc, char *argv[]){ 
struct sockaddr_in sad; /* structure to hold an IP address of server */ //定义一个套接字,用于与服务器通信
int clientSocket; /* socket descriptor */ //定义一个主机信息结构体指针,用于存储主机的信息
struct hostent* ptrh; /* pointer to a host table entry  */ //定义一个字符数组,用于存储要发送给服务器的消息
char Sentence[128]; //定义一个字符数组,用于存储从服务器接收的消息
char modifiedSentence[128]; // argv[0]是执行的程序的名字; atoi转化为整型
host = argv[1]; port = atoi(argv[2]);/*创建socket,参数指明internet地址族,PF_INET:这是第一个参数,表示协议族(Protocol             Family)或地址族(Address Family)。PF_INET 表示使用 IPv4 网络协议。SOCK_STREAM:这是第二个参数,表示套接字类型(Socket Type)。SOCK_STREAM 表示使用面向连接的 TCP 协议。0:这是第三个参数,表示使用默认的协议。对于 SOCK_STREAM 类型的套接字,默认的协议就是 TCP。*/
clientSocket= socket(PF_INET, SOCK_STREAM, 0); 
//从下一行开始,所有缩进的代码都是为了创建连接socket然后和服务器连接//之前有一个sad变量,sad是个结构体变量,分配给内存,先清零//这是因为新声明的变量在内存中可能会有一些旧的、无用的数据,这可能会干扰我们后续的操作memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */ //对sad赋值Internet地址族sad.sin_family= AF_INET; /* set family to Internet */ //将port强制转化为无符号短整型/*htons 是一个在网络编程中常用的函数,全称是 “host to network short”。这个函数的作用是                        将一个16位的数从主机字节序转换为网络字节序。在网络通信中,为了保证数据的正确传输,我们需要统一数据的字节顺序。网络字节序通常是大端字节                序(Big-Endian),也就是最重要的字节(Most Significant Byte,MSB)存储在内存的最低地址        处。主机字节序则取决于你的机器,有的机器是大端字节序,有的机器是小端字节序(Least         Significant Byte,LSB,存储在内存的最低地址处)。因此,在发送数据之前,我们通常会使用         htons 函数将数据从主机字节序转换为网络字节序。例如,如果你的机器是小端字节序,那么一个16位的数 0x1234 在内存中的存储顺序是 34 12。使用 htons 函数后,这个数在内存中的存储顺序就会变为 12 34,符合网络字节序。总的来说,htons 函数的作用就是确保数据在网络上传输时,不同的机器能够正确地解析数据*/sad.sin_port= htons((u_short)port);/*host主机域名。ptrh为结构体指针,gethostbyname就是调用解析器 获取主机的信息,包括主机的IP地址在这段代码中,ptrh 是一个指向 struct hostent 类型的指针。struct hostent 是一个结构            体,它包含了主机的信息,如主机名、别名、地址类型、地址长度和地址列表*/ptrh= gethostbyname(host); /* 将主机的IP地址复制到服务器地址结构体的 sin_addr 字段 */memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length); //将IP地址拷贝到sad.sin_addrconnect(clientSocket, (structsockaddr*)&sad, sizeof(sad));//从用户处得到输入流
gets(Sentence);//发送给服务器用户先前输入的东西
n=write(clientSocket, Sentence, strlen(Sentence)+1); //读取服务器端发过来的转换完毕的字符
n=read(clientSocket, modifiedSentence, sizeof(modifiedSentence));
printf("FROM SERVER: %s\n",modifiedSentence); //关闭连接
close(clientSocket); 
}
  • 服务器

/* server.c  */
// argc参数数量, argv里面的内容是服务器端守候的端口号,只有一个参数void main(int argc, char *argv[]){ 
//sad是作为服务器本地的端节点结构体变量,cad放的是client的端节点的结构体变量
struct sockaddr_in sad; /* structure to hold an IP address  of server*/ 
struct sockaddr_in cad; /*client  */
//welcome socket仅仅有自己的端口号,和对方的无关
int welcomeSocket, connectionSocket; /* socket descriptor */ 
struct hostent *ptrh; /* pointer to a host table entry */ 
//存储客户端发来的信息
char clientSentence[128]; 
//处理客户端发过来的东西后的结果
char capitalizedSentence[128]; 
//端口号
port = atoi(argv[1]);
//建立并bind welcome_socket
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);   memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */ sad.sin_family = AF_INET; /* set family to Internet */ //INADDR_ANY代表本地任何一个IP地址sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */ //格式转化(同客户端)sad.sin_port = htons((u_short)port);/* set the port number */ 
bind(welcomeSocket, (struct sockaddr *)&sad, sizeof(sad));
/* Specify the maximum number of clients that can be queued *///在服务的时候又来了请求,然后这些请求放在这个长度为10的队列,如果超过队列就拒绝listen(welcomeSocket, 10)//服务器进入无限循环,不断接收和处理客户端的连接请求while(1) { //等待用户连接建立请求connectionSocket=accept(welcomeSocket, (structsockaddr*)&cad, &alen);//读取并写入发过来的东西n=read(connectionSocket, clientSentence, sizeof(clientSentence));/* capitalize Sentence and store the result in capitalizedSentence*/n=write(connectionSocket, capitalizedSentence, strlen(capitalizedSentence)+1); close(connectionSocket);  } 
}

UDP套接字编程  

  • 没有握手
  • UDP socket仅仅和本地的IP和端口相关,发送端需要在发送的时候显式的指定对方的IP地址和端口
  • 服务器必须从收到的分组中提取出发送端的IP地址和端口号
  • 传送的数据可能乱序,也可能丢失
  • 无连接的数据单元也叫数据报,所以没办法通过“数据报”这个名字判断TCP还是UDP
     

 C/S交互:UDP

  • recvfrom阻塞,知道对方发来消息

代码示例

  • 客户端

     /* client.c  */void main(int argc, char *argv[])
    { 
    struct sockaddr_in sad; /* structure to hold an IP address */ 
    int clientSocket; /* socket descriptor */ 
    struct hostent *ptrh; /* pointer to a host table entry */ 
    char Sentence[128]; 
    char modifiedSentence[128]; 
    host = argv[1]; port = atoi(argv[2]);
    clientSocket = socket(PF_INET, SOCK_DGRAM, 0); 
    /* determine the server's address */
    memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */ 
    sad.sin_family = AF_INET; /* set family to Internet */ 
    sad.sin_port = htons((u_short)port); 
    ptrh = gethostbyname(host);/* Convert host name to IP address */
    memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);  
    gets(Sentence);
    addr_len =sizeof(struct sockaddr); 
    n=sendto(clientSocket, Sentence, strlen(Sentence)+1,
    (struct sockaddr *) &sad, addr_len); 
    n=recvfrom(clientSocket, modifiedSentence, sizeof(modifiedSentence),
    (struct sockaddr *) &sad, &addr_len);
    printf("FROM SERVER: %s\n",modifiedSentence); 
    close(clientSocket);  
    }
  • 服务器

     /* server.c  */void main(int argc, char *argv[]){ 
    struct sockaddr_in sad; /* structure to hold an IP address */ 
    struct sockaddr_in cad;
    int serverSocket; /* socket descriptor */ 
    struct hostent *ptrh; /* pointer to a host table entry */ 
    char clientSentence[128]; 
    char capitalizedSentence[128]; 
    port = atoi(argv[1]);
    serverSocket = socket(PF_INET, SOCK_DGRAM, 0);   
    memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */ 
    sad.sin_family = AF_INET; /* set family to Internet */ 
    sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */ 
    sad.sin_port = htons((u_short)port);/* set the port number */ 
    bind(serverSocket, (struct sockaddr *)&sad, sizeof(sad));
    while(1) { n=recvfrom(serverSocket, clientSentence, sizeof(clientSentence), 0(struct sockaddr *) &cad, &addr_len );/* capitalize Sentence and store the result in capitalizedSentence*/n=sendto(serverSocket , capitalizedSentence, strlen(capitalizedSentence)+1,(struct sockaddr *) &cad, &addr_len); } 
    }

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

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

相关文章

基于java的社区生活超市管理系统

开发语言:Java 框架:ssm 技术:JSP JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclip…

CSS常用十大选择器(理论+代码实操)

HTML代码实例 注意&#xff1a;拷贝后本地运行注意head标签中的link标签的href属性是否正确 我的目录结构&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Title</title><lin…

详解拷贝构造

拷贝构造的功能 写法&#xff1a; 拷贝构造函数的参数为什么是引用类型 系统自动生成的拷贝构造函数 拷贝构造的深拷贝与浅拷贝 概念 浅拷贝&#xff1a; 深拷贝 小结 拷贝构造的功能 拷贝构造函数可以把曾经实例化好的对象的数据拷贝给新创建的数据 &#xff0c;可见…

ASP.NET基于BS的计算机等级考试系统的设计与实现

摘 要 随着计算机技术的发展及计算机的日益普及&#xff0c;基于B/S结构的考试系统与无纸化办公一样已成为大势所趋。论文详细论述了一个基于B/S结构的计算机等级考试系统的设计过程。软件采用ASP.NET 2005作开发平台&#xff0c;C#作编程语言&#xff0c;SQL Server 2005作…

【DNS】

文章目录 DNS域名解析系统&#xff08;Domain Name System&#xff09;DNS系统需要解决的问题DNS域名解析系统&#xff08;Domain Name System&#xff09;问题1&#xff1a;DNS名字空间(The DNS Name Space&#xff09;DNS名字空间(The DNS Name Space)DNS名字空间(The DNS Na…

边缘计算【智能+安全检测】系列教程--使用OpenCV+GStreamer实现真正的硬解码,完全消除马赛克

通过现有博客的GST_URL = "rtspsrc location=rtsp://admin:abcd1234@192.168.1.64:554/h264/ch01/main/av_stream latency=150 ! rtph264depay ! avdec_h264 ! videorate ! videoconvert ! appsink sync=false" GStreamer的解码方式解码,大多情况应该存在上图马赛克…

解决jenkins运行sh报process apparently never started in XXX

个人记录 问题 process apparently never started in /var/jenkins_home/workspace/ks-springboot_mastertmp/durable-bbfe5f99(running Jenkins temporarily with -Dorg.jenkinsci.plugins.durabletask.BourneShellScript.LAUNCH_DIAGNOSTICStrue might make the problem cl…

架构师系列-搜索引擎ElasticSearch(八)- 集群管理故障恢复

故障转移 集群的master节点会监控集群中的节点状态&#xff0c;如果发现有节点宕机&#xff0c;会立即将宕机节点的分片数据迁移到其它节点&#xff0c;确保数据安全&#xff0c;这个叫做故障转移。 下图中node1是主节点&#xff0c;其他两个节点是从节点 节点故障 此时node1…

卷积神经网络(LeNet5实现对Fashion_MNIST分类

参考6.6. 卷积神经网络&#xff08;LeNet&#xff09; — 动手学深度学习 2.0.0 documentation (d2l.ai) ps&#xff1a;在这里预备使用pythorch 1.对 LeNet 的初步认识 总的来看&#xff0c;LeNet主要分为两个部分&#xff1a; 卷积编码器&#xff1a;由两个卷积层组成; …

OLTP 与 OLAP 系统说明对比和大数据经典架构 Lambda 和 Kappa 说明对比——解读大数据架构(五)

文章目录 前言OLTP 和 OLAPSMP 和 MPPlambda 架构Kappa 架构 前言 本文我们将研究不同类型的大数据架构设计&#xff0c;将讨论 OLTP 和 OLAP 的系统设计&#xff0c;以及有效处理数据的策略包括 SMP 和 MPP 等概念。然后我们将了解经典的 Lambda 架构和 Kappa 架构。 OLTP …

振兴国腾GM8775C MIPIDSI桥接到双 PORT LVDS

GM8775C描述&#xff1a; GM8775C 型 DSI 转双通道 LVDS 发送器产品主要实现将 MIPI DSI 转单 / 双通道 LVDS 功能&#xff0c;MIPI 支持 1/2/3/4 通道可选&#xff0c;每通道最高支持 1Gbps 速率&#xff0c;最大支持 4Gbps 速率。LVDS 时钟频率高达 154MHz &a…

Vue列表渲染

一、Vue列表渲染 1.用 v-for 把一个数组对应为一组元素 我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法&#xff0c;其中 items 是源数据数组&#xff0c;而 item 则是被迭代的数组元素的别名。 <ul id"exampl…

Facebook广告投放数据API对接流程

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、需求背景 App在Facebook、Google等巨头进行广告投放&#xff0c;想要拿到实时广告投放效果数据&#xff0c;如曝光、点击、花费、触…

Django第三方功能的使用

Django第三方功能的使用 Django REST framework前言1、Django--Restframework--coreapi版文档BUG:AssertionError: coreapi must be installed for schema support.How to run Django with Uvicorn webserver?2、序列化类 Serializer的使用模型序列化类 ModelSerializer的使用…

MySQL 社区版 安装总结

很早就安装过MySQL&#xff0c;没有遇到过什么问题&#xff0c;直接next就行了&#xff0c;这次在新电脑上安装却遇到了一些问题&#xff0c;记录一下。 安装的是MySQL社区版&#xff0c;下载地址是www.mysql.com&#xff0c;进入后选择DOWNLOAD页面&#xff0c;选择MySQL Com…

SqlServer专题

目录 1&#xff0c;连接数据库 2&#xff0c;连接池 1.何为连接池&#xff1f; 2.连接池运行原理。 3.如何查看连接池&#xff1f; 4.连接池注意事项。 3&#xff0c;一般SQL语句。 4&#xff0c;控制语句 1.判断语句 2.循环语句 5&#xff0c;视图 1.使用…

<计算机网络自顶向下> P2P应用

纯P2P架构 没有或者极少一直运行的Server&#xff0c;Peer节点间歇上网&#xff0c;每次IP地址都可能变化任意端系统都可以直接通信利用peer的服务能力&#xff0c;可扩展性好例子&#xff1a;文件分发; 流媒体; VoIP类别:两个节点相互上载下载文件&#xff0c;互通有无&#…

C# Solidworks二次开发:相机访问相关API详解

大家好&#xff0c;今天要介绍的API为相机相关的API&#xff0c;这篇文章比较适合女孩子&#xff0c;学会了相机就会拍照了&#xff0c;哈哈。 下面是要介绍的API: &#xff08;1&#xff09;第一个为GetFocalDistance&#xff0c;这个API的含义为获取相机的焦距&#xff0c;…

ASP.NET基于BS的图书销售管理系统的设计与实现

随着Internet的兴起&#xff0c;网络已经成为现代人生活中的一部分&#xff0c;越来越多的人喜欢在网上交易。本系统就是一个基于B/S模式的网络化的图书销售管理系统,采用的是ASP.NET技术&#xff0c;实现了用户注册信息管理、用户信息管理、图书销售点管理、图书信息管理、客户…

特征工程(IV)--特征选择

特征工程 有这么一句话在业界广泛流传&#xff1a;数据和特征决定了机器学习的上限&#xff0c;而模型和算法只是逼近这个上限而已。由此可见&#xff0c;特征工程在机器学习中占有相当重要的地位。在实际应用当中&#xff0c;可以说特征工程是机器学习成功的关键。 特征工程是…