1.网络超时:
在网络通信中,很多操作会使得进程阻塞,TCP套接字中的recv/accept/connect,UDP套接字中的recvfrom。
超时检测的必要性:避免进程在没有数据时无限制的阻塞,当设定的时间到时,进程从原操作返回继续运行。
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);
网络超时检测1:设置socket的属性SO_RCVTIMEO
参考代码:struct timeval tv;
tv.tv_sec = 5; // 设置5秒时间
tv.tv_usec = 0;
setsockopt(sockfd,SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));//设置接收超时
recv()/ recvfrom()//从socket读取数据
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
int main()
{
//监听套接字文件描述符
int listenFd = -1;
//连接套接字的文件描述符
int connFd = -1;
//服务器的地址结构
struct sockaddr_in servAddr = {0};
struct sockaddr_in cliAddr = {0};
socklen_t len = sizeof(cliAddr);
struct timeval tv = {5, 0};//设置5秒时间 {5s, 0um}
int ret;
char buf[100] = {0};
//1.创建套接字
listenFd = socket(PF_INET, SOCK_STREAM, 0);
if(listenFd < 0)
{
perror("socket error!");
return -1;
}
printf("socket ok\n");
//2.绑定ip地址和端口号
servAddr.sin_family = PF_INET;
servAddr.sin_port = htons(10086);
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(listenFd, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(ret < 0)
{
perror("bind error!");
close(listenFd);
return -1;
}
printf("bind ok!\n");
//3.创建监听队列(使得主动的套接字变成可以被连接的被动套接字)
ret = listen(listenFd, 1);
if(ret < 0)
{
perror("listen error\r\n");
close(listenFd);
return -1;
}
printf("listening.....\n");
//设置socket的属性为RECVTIMO
setsockopt(listenFd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
//4.等待并建立连接
while(1)
{
connFd = accept(listenFd, (struct sockaddr *)&cliAddr, &len);
printf("errno = %d\n", errno);
if(connFd < 0 && EAGAIN == errno)
{
printf("no client connect!\n");
continue;
}
else if(connFd < 0 && EAGAIN != errno)
{
perror("accept error!");
close(listenFd);
return -1;
}
break;
}
printf("IP:%s, PORT:%d accept
ok!\n",inet_ntoa(cliAddr.sin_