陕西省建设工程监理协会网站 查询,建筑室内设计软件,wordpress站群插件,标准网站建设哪家好本文由葡萄城技术团队原创并首发。转载请注明出处#xff1a;葡萄城官网#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务#xff0c;赋能开发者。 前言 
本文的内容主要围绕以下几个部分#xff1a; 
TCP/IP的简单介绍。消息的介绍。基于消息分类的传输格式葡萄城官网葡萄城为开发者提供专业的开发工具、解决方案和服务赋能开发者。 前言 
本文的内容主要围绕以下几个部分 
TCP/IP的简单介绍。消息的介绍。基于消息分类的传输格式流类型和XML类型。消息体系的组成。 
TCP/IP的简单介绍 
TCP/IP (传输控制协议/网际协议) 是互联网中的基本通信语言或协议。它其实是一个两层的程序分为高层与低层。高层为传输控制协议负责聚集信息或把文件拆分成更小的包。这些包通过网络传送到接收端的 TCP层接收端的 TCP 层把包还原为原始文件。低层是网际协议它处理每个包的地址部分使这些包正确地到达目的地。网络上的网关计算机根据信息的地址来进行路由选择。即使来自同一文件的分包路由也有可能不同但最后会在目的地汇合。TCP/IP 使用客户端/服务器模式进行通信。 
在架构上TCP/IP 并不完全符合 0SI 的 7 层参考模型。传统的开放式系统互连参考模型是一种通信协议的 7 层抽象的参考模型其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信。这 7 层是: 物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而 TCP/IP 通信协议采用了 4 层的层级结构每一层都呼叫它的下一层所提供的网络来完成自己的需求。这 4 层分别为: 
应用层:应用程序间沟通的层如简单邮件传输协议 (SMTP)、文件传输协议 (FTP)、远程网络访问协议 (Telnet) 等。传输层:在此层中它提供结点间的数据传送和应用程序之间的通信服务主要功能是数据格式化、数据确认和丢失重传等。如传输控制协议 (TCP)、用户数据报协议 (UDP) 等TCP 和 UDP 给数据包加入传输数据并把它传送到下一层中这一层负责传送数据并且确定数据已被送达并接收。互连网络层:负责提供基本的数据封包传送功能让每一个数据包都能够到达目的主机 (但不检查是否被正确接收)如网际协议 (IP)。网络接口层 (主机-网络层): 接收 IP 数据报并进行传输从网络上接收物理帧抽取 IP 数据报转交给下一层管理实际的网络媒体定义如何使用实际网络 (如 Ethernet、Serial Line 等) 来传送数据。 Tcp/IP中常用的函数 
1.Socket函数 
int socket(int domain,int type,int protocol),domain 指明所使用的协议族通常为 PF INET表示互联网协议族(TCP/IP 协议族); type 参数指定 socket 的类型用于 TCP 的SOCK STREAM 或用于 UDP 的 SOCK DGRAM; protocol 通常赋值[0]。socket函数调用返回一个整型 socket 描述符可以在后面调用它。 
2.bind函数 
bind 函数将 socket 与本机上的一个端口相关联随后就可以在该端口监听服务请求。bind 函数原型为: 
int bind(int sockfd,struct sockaddr *my addr, int addrlen)sockfd 是调用 socket 函数返回的 socket 描述符;my addr 是一个指向包含有本机 IP 地址及端口号等信息的 sockaddr 类型的指针:addrlen 常被设置为 sizeof (struct sockaddr)。 
3.connect连接函数 
面向连接的客户程序使用连接 (connect) 函数来配置 socket 并与远端服务器建立一个 TCP 连接其函数原型为: 
int connect(int sockfd, struct sockaddr *serv addr,int addrlen);sockfd 是 socket 函数返回的 socket 描述符; serv addr 是包含远端主机 IP 地址和端口号的指针; addrlen 是远端地址结构的长度。connect 函数在出现错误时返回-1并且设置 errno 为相应的错误码。进行客户端程序设计无须调用 bind 0因为这种情况下只需要知道目的机器的 IP 地址即可而客户通过哪个端口与服务器建立连接并不需要关心socket 执行体程序自动选择一个未被占用的端口并通知程序数据什么时候到达端口。 
4.listen监听函数 
网络监听 (listen) 函数使 socket 处于被动的监听模式并为该socket 建立一个输入数据队列将到达的服务请求保存在此队列中直到程序处理它们。 
int listen(int sockfd, int backlog)sockfd 是 Socket 系统调用返回的 socket 描述符;backlog 指定在请求队列中允许的最大请求数进入的连接请求将在队列中等待接收函数accept 0)(参考下文)。backlog 对队列中等待服务的请求的数目进行了限制通常系统默认值为 20。如果一个服务请求到来时输入队列已满该 socket 将拒绝连接请求客户将收到一个出错信息。 
5.accept接收函数 
accept0函数让服务器接收客户的连接请求。在建立好输入队列后服务器就调用 accept 函数然后睡眠并等待客户的连接请求。 
int accept(int sockfd, void *addr, int *addrlen)sockfd 是被监听的 socket 描述符addr 通常是一个指向sockaddr_in 变量的指针该变量用来存放提出连接请求服务的主机的信息(某台主机从某个端口发出该请求); addrlen 通常为一个指向值为sizeof (struct sockaddr in) 的整型指针变量。出现错误时 accept 函数返回-1 并设置相应的 errno 错误码。 
6.sendto函数和recvfrom函数 
int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen):to 表示目的机的IP 地址和端号信息而 tolen 常常被赋值为 sizeof (struct sockaddr)。sendto 函数返回实际发送的数据字节长度或在出现发送错误时返回-1。 
int recyfrom(int sockfd,void *buf,int len,unsigned int flags,structsockaddr *from,int *fromlen);from 是一个 struct sockaddr 类型的变量该变量保存源主机的 IP 地址及端口号。fromlen 常置为 sizeof (struct sockaddr)当 recvfrom()返回时fromlen 包含实际存入 from 中的数据字节数。recvfrom() 函数返回接收到的字节数或当出现错误时返回-1并设置相应的 errno 错误码。 
7.shutdown函数 
shutdown函数来关闭该 socket。该函数允许你只停止某个方向上的数据传输而另一个方向上的数据传输继续进行。 
int shutdown(int sockfd,int how);sockfd 是需要关闭的 socket 的描述符。参数 how 允许为 shutdown操作选择以下几种方式: 
0一一不允许继续接收数据1–不允许继续发送数据2一一不允许继续发送和接收数据 
shutdown 在操作成功时返回 0在出现错误时返回-1 并设置相应errno 错误码。 
8.fcntl函数 
fcntl函数可以改变已打开的文件的性质。 
int fcntl (int fields, int cmd, .../* int arg */) ;9.getsockopt 与 setsockopt 函数 
这两个函数可以获取或者设置与某个套接字关联的选项。为了操作套接字层的选项应该将层的值指定为 SOL SOCKET。为了操作其他层的选项控制选项的合适协议号必须给出。例如为了表示一个选项是由 TCP 解析层应该设定为协议号 TCP。 
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);10.select函数 
select 函数是一种用于多路复用Multiplexing的系统调用或函数。它通常用于处理多个输入和输出流以实现异步的 I/O 操作。 
int select(int n, fd set * readfds, fd set * writefds, fd set * exceptfds,struct timeval * timeout);参数 n 代表最大的文件描述词加 1参数 readfds、writefds 和exceptfds 称为描述词组是用来回传该描述词的读、写或例外的状况。 
11.poll函数 
int poll(struct pollfd fds[], nfds t nfds, int timeout);其中 fds 是一个 struct pollfd 结构类型的数组用于存放需要检测其状态的 socket 描述字。struct pollfd 的定义如下 
struct pollfd {//descriptor to checkint fd//events of interest on fdshort events;//events that occurred on fdshort revents;
}什么是消息 
消息是分布式应用开发中网络上两个逻辑实体之间进行通信时在编程层面的最小单元。 
对以上定义有以下几点说明 
(1) 消息的概念存在于开发工作中位于编程层面。在系统运行时对应用用户是透明的。 
(2) 网络上的两个逻辑实体是指两个可独立运行的程序它们可以部署于网络中两个不同的物理设备上也可以部署于同一个物理设备上但一般是两个没有父子关系的独立进程 (这一点与 IPC 编程中最基本的消息概念不同)。 
(3) 消息是分布式通信时编程层面的最小单元即无论参与通信的数据量是多还是少程序代码中都通过发送与接收一个或多个消息来实现。 
(4) 网络上两个应用之间的通信包括数据流传输与远程过程(函数)调用两种类型。 
(5) 利用消息可以实现分布式应用之间的结构化数据通信。也就是说编程人员在通信层面面对的不再是实际字节流而是可以由多种数据类型组合而成的结构化数据单元。 
其实这种结构化数据单元本身就是“消息”它对外可以表现为结构或者类。因此当基于以上定义的消息机制建立起来以后程序员在编码过程中当需要进行分布式通信时只需要生成相应的消息然后调用相应的发送与接收接口方便地实现即可而不需要了解 TCP/IP 知识不需要掌握socket 编程的基本技能也不需要考虑串行消息过多、并发消息过多、网络流量控制等其他多方面的问题从而才能真正地将分布式应用开发的精力集中到业务实现上来极大地提高了分布式系统的开发效率与质量特别是大型分布式系统。 
关于消息的存在形式在传统 C 语言中可以是一个结构 struct在面向对象语言中 (C 或 Java)则可以是一个类 class。 
基于消息分类的传输格式 
基于消息传输的格式不同可以将消息分为流消息和XML消息流消息基于二进制字节流式格式传输XML消息基于XML格式的字符串传输。 
流消息 
流消息是指在计算机系统中以流stream的方式传递和处理的消息。流消息由一系列连续的数据组成在发送端按照一定的顺序生成并以流的形式传输到接收端。传输过程中接收端可以逐个读取流中的数据。对于流消息来说无论程序员如何表示消息消息在真正发送之前都需要先转换为二进制流格式这个转换过程称为流化 (Streamlization),也可称序列化 (Serilization) 
XML消息 
XML消息是指使用可扩展标记语言XML作为消息格式的数据传输方式。XML是一种用于描述和存储数据的文本标记语言它使用标签来定义数据的结构和属性。在 XML 消息机制中程序员用 XML 格式表示消息内容之后不需要再为发送传输做任何格式转换工作(不包括为安全传输所做的加密工作)直接就可以以 XML 字符串格式发送出去。XML 消息应用也比较广泛如 Web Service 中的 SOAP 协议就是基于 XML 消息设计实现的。 
举个例子基于流消息的设计与实现方法 
下面小编为大家简单地介绍一下如何在两个应用程序上发送和接受一个人的信息包括身高、姓名和年龄 
1定义一个类存放人的信息 
struct Person {char name[20] float height;int age;
}
struct Person p;
strcpy(p.name ,Michael Zhang)
height  170.00
age  302将信息序列结构化 
char sendStream[1024]  {0};
sprintf(sendStream,|%s|%f%d,p.name, p.height, p.age);3发送方发送字节流 
/*注: 这里省略建立/管理/关闭 TCP 连接的代码*/
char datalen[41]  (0);
sprintf(datalen04d , strlen (sendStream) );
if(SendBytes ( socket, datalen 4)  -1) {return -l;
}
if(SendBytes(socket, sendStream, strlen(sendStream))  -1) {return -1
}注意以上代码中的函数 SendBytes 实际上是保证一定长度的字节流全部成功发送完毕后才返回主要是由于在 socket 上调用 send 或 write函数不能保证一次能将一定长度的字节流发送完。SendBytes 的基本思想是循环发送直至成功发完所有字节其实现代码如下所示: 
int SendBytes (int sd, const void *buffer, unsigned len) {int rez  0;int leftlen  len;int readlen  0:
}
while(true) {rez  write (socket, (char *)bufferreadlen, len-readlen);if(rez  0) {if (errno ! EWOULDBLOCK  errno ! EINTR) {ErrorMsg(Error is serious );DisConnect(socket);}return -l:}readlen  rez;leftlen - rez;if(leftlen  0){break;}}
return len:
}(4)接收方接收字节流 
char datalen[41]  {0}
char receiveStream[1024]  {0}
sprintf(datalen,%04d, strlen(sendStream)) 
if(ReceiveBytes(socket, datalen, 4)  -1 {return -l
}
int packet len  atoi(datalen) :
if(ReceiveBytes (socket, receiveStream, packet len)  -1) {return -l
}ReceiveBytes函数可以参考第三步发送方发送该字节流。 
5字节流反序列化得到结构 
struct Person p;
sscanf(receiveStream,%[|]|%f|%d, p.name, p.height, p.age) ;总结 
本文简单的介绍了TCP/IP协议及其常用的接口函数然后介绍了TCP/IP协议中消息的分类以及传输格式最终以一个简单的消息发送小例子作为收尾。如对内容有何意见建议欢迎大家在评论区中留言和讨论。 
参考书籍《消息设计与开发——分布式应用开发的核心技术》 何小朝 
扩展链接 
从表单驱动到模型驱动解读低代码开发平台的发展趋势 
低代码开发平台是什么 
基于分支的版本管理帮助低代码从项目交付走向定制化产品开发 欢迎了解葡萄城优秀产品 
SpreadJS 纯前端表格控件 活字格 企业级低代码开发平台 Wyn 嵌入式商业智能和报表软件 ActiveReportsJS 纯前端报表控件