前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >16(套接字)

16(套接字)

作者头像
提莫队长
发布2019-02-21 10:44:06
9090
发布2019-02-21 10:44:06
举报
文章被收录于专栏:刘晓杰刘晓杰

1 套接字描述符

套接字描述符在Unix系统中是用文件描述符实现的。事实上,许多处理文件描述符函数(read和write)都可以处理文件描述符 要创建一个套接字,可以调用socket函数

代码语言:javascript
复制
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
        Returns: file (socket) descriptor if OK, 1 on error

参数domain确定通信的特性,通常以AF_开头

这里写图片描述
这里写图片描述

参数type确定参数类型

这里写图片描述
这里写图片描述

参数protocol通常为0,表示选择默认协议

套接字通信是双向的。可以采用shutdown来禁止套接字上的输入输出

代码语言:javascript
复制
#include <sys/socket.h>
int shutdown (int sockfd, int how);
            Returns: 0 if OK, 1 on error

how=SHUT_RD,那么无法从套接字读取数据; how=SHUT_WR,那么无法使用套接字发送数据; how=SHUT_RDWR,那么无法读取和发送数据。 既然可以close套接字,为什么还要shutdown?首先,close只有在最后一个引用被关闭时才释放网络端点。这意味着如果复制一个套接字(比如dup),套接字直到关闭了最后一个引用时才被释放,而shutdown允许使一个套接字处于不活动状态,无论引用他的文件描述符是多少。其次,有时只关闭套接字双向传输中的一个方向会很方便。比如,如果想让进程确定数据发送何时结束,可以关闭该套接字的写端,而读端仍然可以接收数据。

寻址

大端,是指数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中; 小端,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。 处理器字节序和网络字节序之间的转化

代码语言:javascript
复制
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostint32);
        Returns: 32-bit integer in network byte order
uint16_t htons(uint16_t hostint16);
        Returns: 16-bit integer in network byte order
uint32_t ntohl(uint32_t netint32);
        Returns: 32-bit integer in host byte order
uint16_t ntohs(uint16_t netint16);
        Returns: 16-bit integer in host byte order

2 将套接字与地址绑定

代码语言:javascript
复制
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t len);
            Returns: 0 if OK, 1 on error

可以使用getsockname 来发现绑定到一个套接字的地址

代码语言:javascript
复制
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp);
        Returns: 0 if OK, 1 on error

alenp指定缓冲区sockaddr 的大小。返回时会被设置为返回地址的大小。

如果套接字已经和对方连接,调用getpeername来找到对方的地址

代码语言:javascript
复制
#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp);
            Returns: 0 if OK, 1 on error

3 建立连接

代码语言:javascript
复制
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t len);
             Returns: 0 if OK, 1 on error

服务端调用listen来宣告可以接受连接请求

代码语言:javascript
复制
#include <sys/socket.h>
int listen(int sockfd, int backlog);
        Returns: 0 if OK, 1 on error

使用accept获得连接请求并获得连接

代码语言:javascript
复制
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);
Returns: file (socket) descriptor if OK, 1 on error

4 数据传输

三个函数用来发送数据,三个用于接收数据 三个发送数据send,sendto,sendmsg

代码语言:javascript
复制
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags);
这里写图片描述
这里写图片描述
代码语言:javascript
复制
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flags, const struct sockaddr *destaddr, socklen_t destlen);
        Returns: number of bytes sent if OK, 1 on error

和send的区别在于最后制定了目标地址

可以调用带有msghdr结构的sengmsg来指定多重缓冲区传输数据,这和writev很像

代码语言:javascript
复制
#include <sys/socket.h>
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
        Returns: number of bytes sent if OK, 1 on error

Msghdr结构有如下成员:

代码语言:javascript
复制
struct msghdr {
     void          *msg_name;         /* optional address */
     socklen_t      msg_namelen;      /* address size in bytes */
     struct iovec  *msg_iov;          /* array of I/O buffers */
     int            msg_iovlen;       /* number of elements in array */
     void          *msg_control;      /* ancillary data */
     socklen_t      msg_controllen;   /* number of ancillary bytes */
     int            msg_flags;        /* flags for received message */
     .
};

接收数据有三个recv,recvfrom,recvmsg

代码语言:javascript
复制
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);
        Returns: length of message in bytes, 0 if no messages are available and peer has done an orderly shutdown, or 1 on error
这里写图片描述
这里写图片描述

如果有兴趣定位发送者,可以使用recvfrom来得到数据发送者的源地址

代码语言:javascript
复制
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flags, struct sockaddr *restrict addr, socklen_t *restrict addrlen);
            Returns: length of message in bytes, 0 if no messages are available and peer has done an orderly shutdown, or 1 on error

如果addr非空,它将包含数据发送者的套接字端点地址。当调用recvfrom时,需要设置addrlen参数指向一个包含addr所指套接字缓冲区字节大小的整数。返回时,该整数设为该地址的实际字节大小

为了将接收到的数据送入多个缓冲区,或者想接收辅助数据,可以使用recvmsg

代码语言:javascript
复制
#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
            Returns: length of message in bytes, 0 if no messages are available and peer has done an orderly shutdown, or 1 on error

结构msghdr用于指定接收数据的输入缓冲区。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年04月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 套接字描述符
  • 寻址
  • 2 将套接字与地址绑定
  • 3 建立连接
  • 4 数据传输
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档