当前位置:   article > 正文

网络编程套接字socket

网络编程套接字socket

目录

1、套接字的关键因素

1.1 端口号 

1.2 IP地址

1.3 套接字类型 

1.4 套接字常见接口 

1.5 套接字种类

2、网络字节序

结语 


前言:

        网络编程中的套接字(socket)是实现网络通信的关键,换句话来说,套接字像两个端点,而发送方与接收方就是通过这两个端点进行通信的,socket的意思是插座,表示插头和插座连接上后,即发送方和接收方连接上了,然后把电流通过插座流向插头对标发送方与接收方建立了链接。

1、套接字的关键因素

        网络通信的本质是进程间通信,只不过这两个进程不在同一个主机上,而socket要让这两个进程进行通信,则socket必须提供某些字段,以便于让这两个进程找到彼此。socket关键字段介绍如下文。

1.1 端口号 

        端口号属于传输层协议,端口号是一个2字节16bit位的整数 ,他的作用就是找到该主机上的对应进程,并将通信的信息给到该进程。一个进程可以绑定多个端口号,但是一个端口号不能被多个进程绑定,即一个端口号只能对应一个进程

1.2 IP地址

         IP地址是每台主机每台设备在网络中的唯一标识符,通过IP地址就可以在全球网络中定位唯一一台主机或设备。至此,有了端口号和IP地址,就能让发送进程在茫茫的网络中找到接收进程。

        示意图如下:

1.3 套接字类型 

         套接字有两种类型:1、TCP-流式套接字(SOCK_STREAM),2、UDP-数据报套接字(SOCK_DGRAM)。他们都是传输层的协议,在进行通信时,必须对套接字的类型进行定义。

        而TCP和UDP的区别在于:TCP较UDP更加“负责”,主要体现在TCP收到应用层的报文后,会对这个报文负责到底,如果该报文在后面的过程中发生传输失败或者传输时乱序,则TCP会重新发送一份。

        而udp就不一样了,不管这个报文传输成功了还是失败了udp都不会对其维护,udp只负责把从应用层接收到的报文给到下层。

         也正是这样,因此TCP的维护成本会更高。

1.4 套接字常见接口 

         在Linux下使用套接字时,通常会搭配一些常见接口实现通信,接口如下:

  1. // 创建 socket 文件描述符 (TCP/UDP, 客户端和服务器都必须调用此接口)
  2. // 返回一个文件描述符
  3. int socket(int domain, int type, int protocol);
  4. // 绑定端口号 (TCP/UDP, 服务器)
  5. int bind(int socket, const struct sockaddr *address,
  6. socklen_t address_len);
  7. // 开始监听socket (TCP, 服务器)
  8. int listen(int socket, int backlog);
  9. // 接收请求 (TCP, 服务器)
  10. int accept(int socket, struct sockaddr* address,
  11. socklen_t* address_len);
  12. // 建立连接 (TCP, 客户端)
  13. int connect(int sockfd, const struct sockaddr *addr,
  14. socklen_t addrlen);

1.5 套接字种类

        上述接口中有一个叫做struct sockaddr的结构类型,他是套接字种类,种类的不同导致使用的网络层协议的不同,比如sockaddr_in用于IPv4,sockaddr_in6用于IPv6。而上述函数中形参默认使用struct sockaddr*类型,目的就是为了程序的通用性,能够接收IPv4或IPv6以及其他类型的套接字种类。简单来说就是用IPv4协议,则需要定义sockaddr_in类型的变量,用IPv6则定义sockaddr_in6的变量

        套接字种类示意图:

        IPv4、IPv6地址类型分别对应上图的常数AF_INET、AF_INET6。


        基于IPv4编程时, 使用的数据结构是sockaddr_in,这个结构体里主要有三个信息是值得关注的:1、地址类型, 2、端口号, 3、IP地址,在定义sockaddr_in变量时,这三个信息需要我们手动填写,然后再调用函数bind进行绑定。

2、网络字节序

        内存中的数据相对于内存的地址有大小端之分,小端机器指的是低字节内容存在低地址处,大端机器指的是高字节内容存在低地址处。而网络传输数据时,是先传低地址的内容再传高地址的内容,并且规定采用大端字节序的方式传递数据(即使是在小端机器上),所以接收方默认接收的字节是高字节内容,因此如果当前发送主机是小端, 就需要先将数据转成大端模式再进行发送,若是大端则直接发送即可。


        而现实中大部分使用的都是小端机器,若在小端机器上手动把数据转成大端模式,是一件很麻烦的事情,因此在Linux下系统提供了可以帮助我们实现小端转大端的接口,接口如下:

  1. #include <arpa/inet.h>
  2. // 主机序列转网络序列
  3. uint16_t htons(uint16_t hostshort);
  4. uint32_t htonl(uint32_t hostlong);
  5. // 网络序列转主机序列
  6. uint16_t ntohs(uint16_t netshort);
  7. uint32_t ntohl(uint32_t netlong);

        简单的记忆方法:函数名中以to为分隔,h表示host(主机序列),n表示network(网络序列),l表示long类型,s表示short类型。

        比如htonl函数是将32位的长整数从当前主机序列转换为网络序列。如果主机是小端字节序,调用上述函数则转成大端字节序,如果主机是大端字节序,这些函数不做处理直接返回原有值。简单来说,ntohs和ntohl默认形参是大端字节序,而htons和htonl默认返回值是大端字节序

结语 

        以上就是关于网络套接字socket的讲解,socket是应用层实现通信的关键因素,发送方和接收方若想实现通信则必须使用socket套接字。

        最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!! 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/877714
推荐阅读
相关标签
  

闽ICP备14008679号