基本TCP套接字
1.Socket()函数
作用:指定通信的协议类型。要执行网络I/O,必须先调用socket函数。
#include <sys/socket.h>
int socket(int family, int type, int protocal);
/**
@param: family
AF_INET: IPv4协议
AF_INET6: IPV6协议
AF_LOCAL: Unix域协议
AF_Route: 路由套接字
AF_KEY: 密钥套接字
@param: type
SOCK_STREAM:字节流套接字
SOCK_DRAM:数据包套接字
SOCK_SEQPACKET:有序分组套接字
SOCK_RAW:原始套接字
@param:protocal
IPPROTO_TCP::TCP传输协议
IPPROTO_UDP:UDP传输协议
IPPROTO_SCTP:SCTP传输协议
@return:
成功:返回非负套接字描述符(int);
失败:返回-1;
**/
2.Connect()函数
作用:与服务器建立TCP连接
#include<sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
/**
@param::sockfd
套接字描述符,通常由socket()函数创建
@param:servaddr,服务器地址结构的指针
@param:addrlen,参数二地址结构的长度
@return:
成功:返回0;
失败:返回1;
**/
注意:若connect()失败则该套接字不可再使用,必须关闭。关闭后需要重新调用socket()创建套接字。
关于sockaddr结构:
struct sockaddr
{
unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
short int sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
unsigned char sin_zero[8]; /* Same size as struct sockaddr */
};
sin_family:指代协议族,在socket编程中只能是AF_INET
sin_port:存储端口号(使用网络字节顺序)
sin_addr:存储IP地址,使用in_addr这个数据结构
sin_zero:是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
3.bind()函数
作用:把一个本地协议地址赋予一个套接字。
对于网际协议(Internet Protocol,IP),协议地址为32位的IPv4地址或128位的IPv6地址。
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
/**
@param: socketfd,套接字描述符
@param: myaddr,指定地址结构的指针
@param: addrlen,参数二地址结构的长度
@return:
成功:返回0;
失败:返回-1;
**/
调用bind()可以指定IP或端口,可以两者都指定,或者两者都不指定;
绑定IP地址后,该套接字只接收绑定IP地址的客户连接。
struct sockaddr_in servaddr;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //IPv4
struct sockaddr_in6 serv;
serv.sin6_addr = in6addr_any; // IPv6, <netinet/in.h>
4.listen()函数
作用:把为连接的套接字转换成一个被动的套接字。从CLOSED状态转换到LISTEN状态。
socket函数创建的套接字默认被假设为主动套接字,listen函数仅由TCP服务器调用。
#include<sys/socket.h>
int listen(int sockfd, int backlog);
/**
@Param:sockfd,套接字描述符
@Param:backlog,套接字排队的最大连接个数
@return:
成功:返回0;
失败:返回-1;
**/
补充:
内核为任意一个套接字维护两个队列:
(1) 未完成套接字(incomplete connection queue):等待服务器完成TCP三次握手过程,套接字处于SYN_RCVD状态。
(2) 已完成的套接字(complete connection queue):已经完成TCP三路握手过程,处于ESTABLISHED状态。
5.accept()函数
作用:从已完成的队列头中返回下一个已完成的连接。
该函数由TCP服务器调用。
#include<socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t * addrlen);
/**
@param:sockfd,监听套接字描(listening socket)述符
@param:clicaddr,client地址结构指针
@param:addrlen,参数二地址指针长度
@returen:
成功:返回非负描述符,为已连接套接字(connected socket)描述符
失败:返回-1
**/
6. close()函数
作用:关闭套接字
#include <unistd.h>
int close(int sockfd);