Soket网络编程学习记录
文章目录
TCP状态
closing状态产生
SIGPIPE
- 往一个已经接收FIN的套接字中写是允许的,接收到FIN仅仅代表对方不再发送数据。
- 在收到RST段之后,如果再调用write就会产生SIGPIPE信号,对于这个信号的处理通常忽略即可。
signal(SIGPIPE,SIG_IGN)
网络地址
#include <netinet/in.h>
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
字节序
主机字节序
不同主机拥有不同的字节序,主要是大端字节序或者小端字节序,windows主要是小端字节序
网络字节序
网络字节序规定为大端字节序
字节序转换函数
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
介绍
htonl主机字节序转换成网络字节序,long
htons主机字节序转换成网络字节序,short
ntohl网络字节序转换成主机字节序,long
ntohs网络字节序转换为主机字节序,short
地址转换函数
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
INET_ADDRSTRLEN - 16
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
in_addr_t inet_network(const char *cp);
char *inet_ntoa(struct in_addr in);
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);
in_addr_t inet_lnaof(struct in_addr in);
in_addr_t inet_netof(struct in_addr in);
介绍
inet_aton将点分十进制的IP地址转换成十进制(网络字节序),存储在inp指针对象中。返回非0值表示成功,0表示失败。
inet_aton返回值为1表示解析成功,返回值为0表示失败。
inet_addr将点分十进制IPV4字符串转换成十进制网络字节序。输入不合法,返回值为INADDR_NONE(-1)。使用该函数需要注意255.255.255.255表示一个不合法地址。使用inet_aton,inet_pton或者getaddrinfo来避免这一个问题,这些函数提供了清晰地错误返回。
inet_lnaof局部网络地址部分返回互联网地址。返回的值按主机字节顺序排列。
typedef uint32_t in_addr_t;
struct in_addr {
in_addr_t s_addr;
};
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);
介绍
inet_pton:成功返回1,src非法返回0,出错返回-1
inet_ntop:成功返回非NULL值,失败返回NULL值
size表示dst的长度
协议 | 地址类型 |
---|---|
AF_INET | struct in_addr |
AF_INET6 | struct in6_addr |
套接字主要类型
- 流式套接字(SOCK_STREAM)提供面向连接的、可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收
- 数据报式套接字(SOKC_DGRAM)
提供无连接服务。不提供无措保证,数据可能丢失或重复,并且接收顺序混乱。 - 原始套接字(SOCK_RAW)
socket函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
介绍
socket创建通信端点并返回描述符。
domain指定通信域,并选择进行通信的协议。<sys/socket.h>。
套接字具有指定点分类型,该类型指定通信语义。
protocol指定用于socket的特定协议.通常只有一个协议对应socket的对应协议族,
在这种情况下,协议可以指定为0。但是某些协议族可能对应多种协议,这时需要
指定协议. The protocol number to use is specific to the “communication
domain” in which communication is to take place; see protocols(5). See
getprotoent(3) on how to map protocol name strings to protocol numbers.
返回值
成功:文件描述符
失败:-1
domian Name | Purpose | Man page |
---|---|---|
AF_UNIX, AF_LOCAL | Unix域协议 | unix(7) |
AF_INET | IPv4 | ip(7) |
AF_INET6 | IPv6 | ipv6(7) |
AF_IPX | IPX - Novell protocols | |
AF_NETLINK | Kernel user interface device | netlink(7) |
AF_X25 | ITU-T X.25 / ISO-8208 protocol | x25(7) |
AF_AX25 | Amateur radio AX.25 protocol | |
AF_ATMPVC | Access to raw ATM PVCs | |
AF_APPLETALK | AppleTalk | ddp(7) |
AF_PACKET | Low level packet interface | packet(7) |
AF_ALG | Interface to kernel crypto API |
type | 介绍 |
---|---|
SOCK_STREAM | 字节流套接字 |
SOCK_DGRAM | 数据报套接字 |
SOCK_RAW | 原始套接字 |
SOCK_RDM | Provides a reliable datagram layer that does not guarantee ordering. |
protocol | 说明 |
---|---|
IPPROTO_TCP | TCP传输协议 |
IPPROTO_UDP | UDP传输协议 |
IPPROTO_SCTP | SCTP传输协议 |
类型 | AF_INET | AF_INET6 | AF_LOCAL | AF_ROUTE | AF_KEY |
---|---|---|---|---|---|
SOCK_STREAM | TCP/SCTP | TCP/SCTP | 是 | - | - |
SOCK_DGRAM | UDP | UDP | 是 | - | - |
SOCK_SEQPACKET | SCTP | SCTP | 是 | - | - |
SOCK_RAW | IPV4 | IPV6 | - | 是 | 是 |
bind函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
介绍
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
返回值:
成功:0
失败:-1
memset/bzero函数
#include <string.h>
void *memset(void *s, int c, size_t n);
void bzero(void *s, size_t n);
返回值
s的指针
listen函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
介绍
backlog为连个队列的连接总数
SOMAXCONN:128 表示连接队列长度
返回值
成功:0
失败:-1
listen函数应该在socket和bind函数调用之后,accept函数调用之前调用
对于给定的监听套接口,内核需要维护两个队列:
- 已由客户端发出并到达服务器,服务器正在等待完成相应TCP三次握手过程
- 已完成连接的队列
accept函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
介绍
如果sockfd为非阻塞,而且连接队列中没有连接,errno值设置为EAGAIN或EWOULDBLOCK.
返回值
成功:文件描述符
失败:-1
getsockopt/setsockopt
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
介绍
optval是指向某个变量的指针,socklen_t表示该变量的长度u32_int
返回值
成功:0
失败:-1
SOL_SOCKET
选项名称 | 说明 | 数据类型 |
---|---|---|
SO_BROADCAST | 允许发送广播数据 | int |
SO_DEBUG | 允许调试 | int |
SO_DONTROUTE | 不查找路由 | int |
SO_ERROR | 获得套接字错误 | int |
SO_KEEPALIVE | 周期性的测试连接是否存活 | int |
SO_LINGER | 若有数据 | struct linger |
SO_OOBINLINE | 带外数据放入正常数据流 | int |
SO_RCVBUF | 接收缓冲区大小 | int |
SO_SNDBUF | 发送缓冲区大小 | int |
SO_RCVLOWAT | 接收缓冲区下限 | int |
SO_SNDLOWAT | 发送缓冲区下限 | int |
SO_RCVTIMEO | 接收超时 | struct timeval |
SO_SNDTIMEO | 发送超时 | struct timeval |
SO_REUSERADDR | 允许重用本地地址和端口 | int |
SO_TYPE | 获得套接字类型 | int |
SO_BSDCOMPAT | 与BSD系统兼容 | int |
SO_BROADCAST
本选项开启或者禁止进程发送广播的能力。只有数据报套接字支持广播,并且还必须是在支持广播消息的网络上。
SO_DEBUG
本选项支持TCP。当给一个TCP套接字开启本选项时,内核将为TCP在该套接字发送和接收所有分组保留详细的跟踪信息。这些信息将保存在内核的某个环形缓冲区中,并可使用trpt程序进行检查。
SO_DONTROUTE
规定外出的分组将绕过底层协议的正常路由机制。举例来说IPv4情况下外出分组将被定向到适当的本地接口,也就是由其目的地址的网络和子网部分确定的本地接口。如果这样的本地接口无法由目的地址确定,那么返回ENETUNREACH错误。
给函数send、sendto或sendmsg使用MSG_DONTROUTE标志也能在个别的数据报上取得与本地选项相同的效果。
路由守护进程(routed和gated)经常使用本选项来绕过路由表,以强制将分组从特定接口送出
SO_ERROR
只能获取不能设置该字段
一个套接字上发生错误时,内核中的协议模块将该套接字的名为so_error的变量设置为标准Unix Exxx值中的一个,我们称它为该套接字的待处理错误。
- 如果进程阻塞在对该套接字的select调用上,无论是检查可读条件还是可写条件,select军返回并设置其中一个或所有两个条件
- 如果进程使用信号驱动IO模型,就会给进程组产生一个SIGIO信号
进程然后可以通过访问SO_ERROR套接字选项获取so_error值。由getsockopt返回整数值就是该套接字的待处理错误。so_error随后由内核复位为0 。
当进程调用read且没有数据返回时,如果so_er