完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
Socket 通常也称作"套接字",是支持 TCP/IP 协议的网络通信应用的基本操作单元,可以用来实现网间不同虚拟机或不同计算机之间的通信。使用TCP/IP协议的应用程序通过在客户端和服务器各自创建一个 Socket ,然后通过操作各自的 Socket 就可以完成客户端和服务器的连接以及数据传输的任务了。
Socket 的本质是编程接口( API ),是对 TCP/IP 的封装。使开发者不需要面对复杂的 TCP/IP 协议族,只需要调用几个较简单的 Socket API 就可以完成网络通信了。 RT-Thread 中的 SAL 抽象层 提供完整的 BSD Socket 相关 API。 BSD Socket 相关 API [tr] 名称 作用 [/tr]
要学用套接字编程,一定要了解 TCP/UDP 协议。TCP/UDP 协议工作在 TPC/IP 协议栈的传输层,如下图所示: TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的协议,使用该协议时,可以保证客户端和服务端的连接是可靠和安全的。使用 TCP 协议进行通信之前,通信双方必须先建立连接,然后再进行数据传输,通信结束后终止连接。 优点:能保证可靠性、稳定性。 适用场景:TCP适合用于端到端的通信,适用于对可靠性要求较高的服务。 基于 TCP 的 socket 编程流程如下图所示: UDP(User Datagram Protocol 用户数据报协议)是一种非面向连接的协议,它不能保证网络连接的可靠性。 客户端发送数据之前并不会去服务器建立连接,而是直接将数据打包发送出去。当服务器接收数据时它也不向发送方提供确认信息,如果出现丢失包或重份包的情况,也不会向发送方发出差错报文。 优点:控制选项少,无须建立连接,从而使得数据传输过程中的延迟小、数据传输效率高。 适用场景:UDP适合对可靠性不高,或网络质量有保障,或对实时性要求较高的应用程序。 基于 UDP 的 socket 编程流程如下图所示: API 详解 socket 使用 socket 通信之前,通信双方都需要各自建立一个 socket。我们通过调用 socket 函数来创建一个 socket 套接字: int socket(int domain, int type, int protocol) 函数参数 [tr] 参数 描述 [/tr]
AF_INET Ipv4 AF_INET6 Ipv6 AF_UNIX UNIX 域 AF_UNSPEC 未指定 type 参数支持下列参数: SOCK_DGRAM 长度固定的、无连接的不可靠的报文传递(UDP) SOCK_RAM IP 协议的数据报接口 SOCK_STREAM 有序、可靠、双向的面向连接字节流(TCP) protocol 参数: 通常是 0 ,表示按给定的 domain 和 type 选择默认传输协议。在 AF_INET 通信域中套接字类型 SOCK_STREAM 的默认传输协议是 TCP。在 AF_INET 通信域中套接字类型 SOCK_DGRAM 的默认传输协议是 UDP。 当对同一 domian 和 type 支持多个协议时,可以使用 protocol 参数选择一个特定协议。 函数返回 返回一个 socket 描述符,它唯一标识一个 socket。这个 socket 描述符 跟文件描述符 一样,后续的操作都有用到它,比如,把它作为参数,通过它来进行一些读写操作等。 bind bind 函数用来将套接字与计算机上的一个端口号相绑定,进而在该端口监听服务请求,该函数的一般形式如下: int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) 函数参数 [tr] 参数 描述 [/tr]
struct sockaddr { u8_t sa_len; u8_t sa_family; char sa_data[14]; }; 在 IPv4 因特网域(AF_INET)中,我们使用 sockaddr_in 结构体来代替 sockaddr 结构体: struct sockaddr_in { u8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[SIN_ZERO_LEN]; }; 其中,
注意事项 当调用 bind 函数时,不要将端口号设为小于 1024 的值,因为 1-1024 为系统的保留端口号,我们可以选择大于 1024 的任何一个未被占用的端口号。 listen listen 函数用来将套接字设为监听模式,并在套接字指定的端口上开始监听,以便对到达的服务请求进行处理。listen 函数的一般形式如下: int listen(int sockfd, int backlog) 函数参数 [tr] 参数 描述 [/tr]
accept 函数用来从完全建立的连接的队列中接受一个连接,它的一般形式如下: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) 函数参数 [tr] 参数 描述 [/tr]
connect connect 函数用来与服务器建立一个 TCP 连接,它的一般形式如下: int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) 函数参数 [tr] 参数 描述 [/tr]
send 函数用来在面向连接的数据流 socket 模式下发送数据,send 函数的一般形式如下: int send(int sockfd, const void *msg, size_t len, int flags) 函数参数 [tr] 参数 描述 [/tr]
recv recv 函数用来在面向连接的数据流 socket 模式下接收数据,recv 函数的一般形式如下: int recv(int sockfd, void *buf, size_t len, int flags) 函数参数 [tr] 参数 描述 [/tr]
sendto 函数用来在无连接的数据报 socket 模式下发送数据,sendto 函数的一般形式如下: int sendto(int sockfd, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) 函数参数 [tr] 参数 描述 [/tr]
recvfrom函数用来在无连接的数据报 socket 模式下接收数据,recvfrom 函数的一般形式如下: int recvfrom(int sockfd, void*buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) 函数参数 [tr] 参数 描述 [/tr]
closesocket 在传输完数据之后关闭 socket 并释放资源的函数,closesocket 函数的一般形式如下: int closesocket(int sockfd) 函数参数 [tr] 参数 描述 [/tr]
shutdown 允许进行单向的关闭操作,或是全部禁止掉,shutdown 函数的一般形式如下: int shutdown(int sockfd, int how) 函数参数 [tr] 参数 描述 [/tr]
SHUT_RD 关闭接收信道 SHUT_WR 关闭发送信道 SHUT_RDWR 将发送和接收信道全部关闭 函数返回 返回 0 表示成功 gethostbyname 此函数可以通过域名来获取主机的 IP 地址等信息,它的一般形式如下: struct hostent* gethostbyname(const char*name) 函数参数 [tr] 参数 描述 [/tr]
hostent 结构体定义如下: struct hostent { char *h_name; /* 主机正式域名 */ char **h_aliases; /* 主机的别名数组 */ int h_addrtype; /* 协议类型,对于 TCP/IP 为 AF_INET */ int h_length; /* 协议的字节长度,对于 IPv4 为 4 个字节 */ char **h_addr_list; /* 地址的列表*/ #define h_addr h_addr_list[0] /* 保持向后兼容 */ }; getsockname 此函数可以获取本地主机的信息,它的一般形式如下: int getsockname(int sockfd, struct sockaddr *name, socklen_t *namelen) 函数参数 [tr] 参数 描述 [/tr]
此函数可以得到与本地主机连接的远程主机的信息,它的一般形式如下: int getpeername(int socket, struct sockaddr *name, socklen_t *namelen) 函数参数 [tr] 参数 描述 [/tr]
设置套接字控制模式,它的一般形式如下: int ioctlsocket(int sockfd, long cmd, void *arg) 函数参数 [tr] 参数 描述 [/tr]
FIONBIO 开启或关闭套接字的非阻塞模式,arg 参数为 1 开启非阻塞,为 0 关闭非阻塞。 注意事项 在网络中都采用大端字节序,但是不同的嵌入式系统,其字节序不一定都是大端格式,相反小端字节序倒是很常见,比如 STM32。我们在设置 IP 和端口号时,要根据自己的平台特点进行必要的字节序转换。 下面给出套接字字节转换函数的列表: htons() —— "Host to Network Short" 主机字节顺序转换为网络字节顺序 htonl() —— "Host to Network Long" 主机字节顺序转换为网络字节顺序 ntohs() —— "Network to Host Short" 网络字节顺序转换为主机字节顺序 ntohl() —— "Network to Host Long" 网络字节顺序转换为主机字节顺序 对于一个“192.168.2.1”这种字符串形式的 IP 地址,我们如何将其正确的转换为网络字节序呢? 可以使用 inet_addr(“192.168.2.1”),结果直接就是网络字节序了; 我们也可以使用 inet_ntoa()(“ntoa”代表“Network to ASCII”)函数将一个长整形的 IP 地址转换为一个字符串。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
786 浏览 0 评论
4210 浏览 0 评论
如何使用python调起UDE STK5.2进行下载自动化下载呢?
2520 浏览 0 评论
开启全新AI时代 智能嵌入式系统快速发展——“第六届国产嵌入式操作系统技术与产业发展论坛”圆满结束
2926 浏览 0 评论
获奖公布!2024 RT-Thread全球巡回线下培训火热来袭!报名提问有奖!
31442 浏览 11 评论
72897 浏览 21 评论
浏览过的版块 |
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 04:45 , Processed in 0.614217 second(s), Total 71, Slave 54 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号