【APUE】套接字


  • 套接字描述符
套接字是通信端点的抽象,套接字描述符在unix系统中都是用文件描述符实现的。许多处理文件描述符的函数都可以处理套接字描述符。
 
 
int socket(int domain, int type, int protocol)
创建一个套接字
domain表示通信的特性,包括地址格式
type确定套接字的类型,进一步确定通信特征
protocol一般是0,但是当同一域和套接字类型支持多个协议时,可以使用该参数使用一个特定协议
 
 
int shutdown(int sockfd, int how)
套接字是双向的, 可以采用该函数来关闭套接字上的输入或者输出
how:SHUT_RD SHUT_WR SHUT_RDWR
 
 
 
  • 字节序
是一个处理器架构特性,用于指示像整数这样的大数据类型的内部字节顺序
大端字节序:最大字节地址对应于数字最低有效字节
小端字节序:相反
不管字节如何排序,数字最高位总是在最左边,最低总是在最右边
TCP/IP采用大端字节序
#include<arpa/inet.h>
uint32_t htol(unit_t hostint32);
uint16_t htos(unit_t hostint16);
uint32_t ntohl(unit_t hostint32);
uint16_t ntohs(unit_t hostint16);
 
地址格式sockaddr
Linux中表示为
struct sockaddr{
    sa_family_t sa_family;
    char sa_data[14];
}
 
因特网地址定义在<netinet/in.h>
struct in_addr{
    in_addr_t s_addr;
}
struct sockaddr_in{
    sa_family_t sin_family;
    in_port_t sin_port;
    struct in_addr sin_addr;
}
 
 
 
  • 将套接字与地址绑定
对于服务器,需要给一个接受客户端请求的套接字绑定一个众所周知的地址。
int bind(int sockfd, const struct sockaddr *addr, socklen_t len);
 
发现绑定到一个套接字的地址
int getsockname(int sockf, struct sockaddr *addr, socklen_t *alenp)
 
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *alenp)
如果套接字已经和对方连接,可以找到对方的地址
 
 
 
 
  • 建立连接
如果处理的是面向连接的网络服务,在开始传输数据之前,需要先建立连接
int connect(int sockfd, const struct *addr, socklen_t len)
如果sockfd没有绑定到一个地址,connect就会给调用者绑定一个默认地址。
 
当connect用于无连接的网络服务,所有发送报文的目的地设为该函数中所指定的地址,这样每次传送报文时就不需要再提供地址。另外,仅能接收来自指定地址的报文。
 
服务器调用listen来宣告可以接收连接请求
int listen(int sockfd, int backlog)
 
accept获得连接请求并且建立连接
int accept(int sockfd, struct sockaddr *addr, socklen_t *len);
返回套接字描述符
如果没有连接需要处理,accept会阻塞,如果sockfd处于非阻塞模式,会返回-1并将errno设置为EAGAIN或者EWOULDBLOCK
 
 
 
 
  • 数据传输
只要建立连接,就可以用read和write来处理套接字,这使得原来用于处理文件的子程序和子进程可以处理套接字。
 
还有6个传递数据的套接字函数,专门用于处理套接字
 
3个发送数据的函数:
ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags);
发送数据,可以指定标志来改变处理传输数据的方式
 
ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flags, const struct sockaddr *destaddr, socklen_t destlen)
在send的基础上允许在无连接的套接字上指定一个目标地址
对于面向连接的服务,目的地址是忽略的,但是无连接的套接字只有在预设了地址时才可以使用send
 
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
可以指定多重缓冲区传输数据,和writev很像
 
 
类似的还有三个接收数据的函数
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags)
ssize_t recvfrom(int sockfd, void buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen)
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
 
 
 
 
  • 套接字选项
提供两个套接字选项接口来控制套接字的行为。一个接口用来设置,一个用来查询
可以做三个层次的操作
1)通用选项,工作在所有套接字上
2)在套接字层次管理的选项,但是依赖于下层协议的支持
3)特定于某个协议的选项,为每个协议所有
 
int setsockopt(int sockfd, int level, int option, const void *val, socklen_t len)
设置套接字选项
int getsockopt(int sockfd, int level, int option, void *val, socklen_t *lenp)
获取套接字选项
 
 
 
  • 带外数据
允许更高优先级的数据比普通数据优先传输。
TCP支持但是UDP不支持
 
posted @ 2012-09-24 18:46  w0w0  阅读(326)  评论(0编辑  收藏  举报