linux网络编程系列-TCP及常用接口分析
TCP编程示例图:
头文件:
常用头文件"arpa/inet.h", "sys/socket.h","netinet/in.h"
函数原型:
int socket(int family, int type, int protocol)
family:通信协议族,IP protocol family为AF_INET(PF_INET),值是2;
type:套接字类型(连接类型)。
SOCK_STREAM(1)为Sequenced, reliable, connection-based byte streams(TCP);
SOCK_DGRAM(2)为Connectionless, unreliable datagrams of fixed maximum length(UDP);
其他还有SOCK_RAW(3), SOCK_RDM(4), SOCK_SEQPACKET(5),SOCKET_PACKET(10)。
protocol:不解释了,没理解,一般写为0,系统自动选择合适的协议。返回:套接字描述符。
int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen)
connect:客户端调用;servaddr套接口地址结构,包含有服务器的IP地址和端口号;返回0成功,-1出错;每当connect失败,都必须关闭套接口,重新调用socket。
int bind(int sockfd, const struct sockaddr* myaddr, socklen_t addrlen)
bind:服务端调用,给套接口分配一个本地协议地址;myaddr包含本地分配的ip和端口;返回0成功,-1出错。客户端不调用bind由内核随意分配一个端口,而服务端必须调用明确指出端口。
int listen(int sockfd, int backlog)
listen:socket函数创建套接口默认为主动套接口(要发起连接的),listen会将未连接的套接口转换成被动套接口(接收连接),返回-1出错0成功。
int accept(int sockfd, struct sockaddr* cliaddr, socklen_t* addrlen)
accept:从已完成的连接队列头部返回一个已完成连接;成功返回内核自动生成的一个全新描述字代表与客户端的TCP连接,第一个参数sockfd常称为监听套接口,返回值称为已连接套接口,返回-1出错。cliaddr为客户端的协议地址,addrlen为该地址大小。一个服务器常常只生成一个监听套接口且一直存在,直到该服务器关闭。内核为每个被接受的客户连接创建一个已连接套接口(三路握手已完成的连接)。
监听套接口的两个队列:
int close(int sockfd)
close:将套接口sockfd做上已关闭标记,并立即返回。该描述字不能再用作read或write的参数,但TCP会继续发送已排队待发的数据,然后按照TCP连接终止序列进行操作。
数据读写:
标准读写
ssize_t write(int fd, const void *buf, size_t n) ssize_t read (int fd, void *buf, size_t n)
网络读写
ssize_t send (int fd, const void *buf, size_t n, int flags) ssize_t recv (int fd, void *buf, size_t n, int flags)
何时阻塞:
•读阻塞,receive buffer is empty
socklen_t表示套接字的大小,4Byte,是一个uint32类型。
struct sockaddr表示套接字的连接地址,通常用struct sockaddr_in代替。二者大小相同,sockaddr_in用了多余的char数组来补齐大小。
struct sockaddr { sa_family_t sa_family;//2个字节,地址协议族,unsigned short int char sa_data[14];//地址 }
struct sockaddr_in { sa_family_t sin_family; //2Byte in_port_t sin_port; /* Port number. 2Byte*/ struct in_addr sin_addr; /* Internet address. 4Byte*/ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)]; }; typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; }; #define __SOCKADDR_COMMON_SIZE sizeof(unsigned short int)
char *inet_ntoa (struct in_addr __in)
将IP地址由网络字节序转为可理解的点分十进制(net to ascii)
int inet_pton (int af, const char* cp, void* buf)
将点分十进制ip转为网络字节序,af为地址协议族(AF_INET),cp为ip地址(10.8.3.2), buf为保存转换结果的地址。常用如下:
struct sockaddr_in addr; inet_pton(AF_INET, "10.3.17.75", &addr.sin_addr);
in_addr_t inet_addr (const char *cp)
同inet_pton效果相同,将ip转为网络字节序
struct sockaddr_in sin; sin.sin_addr.s_addr = inet_addr("10.17.25.34");