套接字基础

1.
int socket(int domain,int type, int protocol)
int sockfd=socket(,,,);

返回文件描述符,-1 表示错误
需要头文件: <sys/types.h> <sys/socket.h>
domain : AF_INET,PF_INET,AF_INET6, IPv4 or IPV6
type:SOCK_STREAM, SOCK_DGRAM, tcp or udp
protocol: 通常默认为0, 表示系统自动选择合适的协议类型

2. IPV4套接字地址

struct sockaddr_in{
sa_family_t sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};

struct in_addr{
uint32_t s_addr;
}

3. int connect(int sockfd,const struct sockaddr *servaddr,socklen_t addrlen)

0表示成功,-1表示失败, 非阻塞函数,立即返回

4. int listen(int sockfd,int backlog)

backlog  参数是指完成TCP三次握手后已经成功建立TCP连接的队列的长度,服务器执行ACCEPT操作从该队列中取下一个连接进行后续处理,BACKLO的默认值是128

5. int accept (int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen);

TCP服务器使用ACCEPT 函数从BACKLOG队列中返回下一个成功建立的连接), 如果BACKLOG队列为空,则服务器进程将被阻塞

如果该函数调用成功,它的返回值是一个新的套接字描述符,称为连接套接字,服务器使用该套接字和亿建立的客户端进行通信,而原有的监听套接字继续接受后续新客户端发来的连接请求

6. 其它

read/write/: TCP 连接用的函数

recvfrom/sendto UDP, 数据包套接字用到的函数

7.

if (listen(sockfd,128) == -1)
....

while(1){
if((new_fd = accept()) == -1)
....

for(;;)
{
len= read()

if(len>0)
处理读到的数据
}


}

此种模式下服务器只能对所接受到的一个客户端的连接请求进行处理,不能太接受其它客户端的连接请求,只有处理完,才能处理下一个请求

7. 使用子进程来出来


if (listen(sockfd,128) == -1)
....

while(1){
if((new_fd = accept()) == -1)
....

pid=fork()
switch(pid)
case :0 子进程
read
处理读入数据



}

高级套接字

8. setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t optlen)

level: SOL_SOCKET, SOL_TCP

a SO_KEEPALIVE: 若在两小时内TCP连接双方没有发送过任何数据,自动向对方发送活动探测,并且接受方必须回应

b SO_RECVBUF SO_SNDBUF 调整发送缓存区和接受缓存区的大小

c SO_RCVLOWAT SO_SNDLOWAT 最低接收阀值和最低发送阀值

d SO_REUSEADDR : 服务器再次绑定到一个端口,无需等待。

9.

文件描述符

FD_ZERO(fd_set *fdset); 清空
FD_SET(int fd,fd_set *fdset); 添加
FD_CLR(int fd,fd_set *fdset); 删除某个
FD_ISSET(int fd,fd_set *fdset); 坚持某个是否被置位

fd_set rfds,orfds;
FD_ZERO(&orfds);
FD_SET(STDIN_FILENO,&orfds);
maxfd=STDIN_FILENO;

FD_SET(STDIN_FILENO,&orfds);
if((sockfd > maxfd)
maxfd=sockfd

rfds=orfds;

用SELECT 开始等待可读文件描述符集合可用的通知


ret = select(maxfd+1,&rfds,NULL,NULL,NULL)

if(ret == -1)
error
else
for(int i = 0; i < MAX_CONNECTION; i++)
{
if(FD_ISSET(sockfd,,&rfds)
read...
else if(FD_ISSET(STDIN_FILENO,&rfds)
write...
}

缺点
_FD_SETSIZE 最大值为1024, 若修改,需要重新编译内核,需要轮询

当使用FD_ISSET时, 需要遍历所有集合












你可能感兴趣的:(套接字)