TCP套接口编程的基本函数
套接字工作过程如下:
服务器首先启动,通过调用socket()建立一个套接字,然后调用bind()将该套接字和本地网络地址联系在一起,再调用listen()使套接字做好侦听准备,并规定它的请求队列的长度,之后调用accept()来接收链接。客户在建立套接字之后就可调用connect()和服务器连接。连接一旦建立,客户机和服务器之间就可以通过调用read()和write()来发送和接收数据。最后待数据传输结束后,双方调用close()关闭套接字。如下图所示:
一、socket函数
#include <sys/socket.h>
int socket(int family, int type, int protocol); 返回:非负描述字——成功;-1——出错
参数:family: AF_INET-----IPv4 协议
AF_INET6----IPv6 协议
AF_LOCAL---Unix 域协议
AF_ROUTE---路由器套接口
AF_KEY-------密钥套接口
type: SOCK_STREAM--------字节流套接口
SOCK_DGRAM---------数据包套接口
SOCK_SEQPACKET----有序分组套接口
SOCK_RAW--------------原始套接口
protocol: IPPROTO_TCP------------TCP 传输协议
IPPROTO_UDP-----------UDP 传输协议
IPPROTO_SCTP----------SCTP 传输协议
通常,protocol设置为0.
二、bind函数
函数bind给套接口分配一个本地协议地址,对于网际协议,协议地址是32位IPv4地址或128位IPv6地址与16位的TCP或UDP端口号的组合。
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); 返回:0——成功; -1——出错
参数:sockfd: 套接口描述字
myaddr: 指向特定于协议的地址结构的指针
sockaddr里面含有本地IP地址和端口,也可以将地址设置为通配地址,
INADDR_ANY来指定通配地址,一般为0。它告知内核去选IP 地址。
addrlen: 该地址结构的长度
struct sockaddr_in {
short int sin_family; /* Internet地址族*/
unsigned short int sin_port; /* 端口号*/
struct in_addr sin_addr; /* Internet地址*/
unsigned char sin_zero[8]; /* 添0(和struct sockaddr一样大小)*/
};
三、listen函数
listen将未连接的套接口转换成被动套接口,指示内核应接受指向此套接口的连接请求。
#include <sys/socket.h>
int listen(int sockfd, int backlog); 返回:0——成功;-1——出错
参数:sockfd: 套接口描述字
backlog: 内核为此套接口排队的最大连接个数
四、accept函数
accept由TCP服务器调用,从已完成连接队列头返回下一个已完成连接。若已完成连接队列为空,则进程睡眠(假定套接口为缺省的阻塞方式)。
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); 返回:非负描述字——成功;-1——出错
参数:sockfd: 套接口描述字
cliaddr: 用来返回连接对方进程(客户)的协议地址
addrlen: 值—结果参数。调用前,*addrlen所指的整数值为由cliaddr所指的套接口地址结构的
长度;返回时,此整数值为由内核存在此套接口地址结构内的准确字节数
如果accept执行成功,则返回值为由内核自动生成的一个全新描述字,代表与客户的TCP连接。accept的第一个参数常称为监听套接口描述字,它的返回值常称为已连接套接口描述字。
五、connect函数
TCP客户用connect来建立一个与TCP服务器的连接。connect激发TCP的三路握手过程,且仅在连接建立成功或出错时才返回。
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen); 返回:0——成功;-1——出错
参数:sockfd: 套接口描述字
servaddr: 指向套接口地址结构的指针
addrlen: 该地址结构的长度
六、fork函数
#include <unistd.h>
pid_t fork(void); 返回:在子进程中为0,在父进程中为子进程ID,-1——出错
fork调用一次但返回两次。在调用进程(父进程),返回一次,返回值是新派生进程(子进程)的进程ID号;在子进程还返回一次,返回值为0。可通过返回值来判断当前进程是父进程还是子进程。
父进程中调用fork前打开的所有描述字在fork返回后都是共享的。网络服务器利用此特性:父进程调用accept,然后调用fork,这样,已连接套接口就在父进程与子进程间共享,一般来说,接下来就是子进程读、写已连接套接口,而父进程则关闭已连接套接口,继续监听。
七、close函数
close用来关闭套接口,终止TCP连接。
#include <unistd.h>
int close(int sockfd); 返回:0——成功;-1——出错
八、getsockname和getpeername函数
getsockname返回与套接口关联的本地协议地址,getpeername返回与套接口关联的远程协议地址。
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
两者均返回:0——成功;-1——出错