您的位置:首页 > 理论基础 > 计算机网络

设置socket超时时间的两种方式

2016-12-31 17:01 597 查看
最近在编写fastcgi中,要通过udp请求后台其他服务数据。如果使用阻塞socket,万一由于网络等原因没有数据包返回,那么recvfrom将一直阻塞;如果使用非阻塞socket,后端服务还没有处理完请求返回数据前,recvfrom很可能已经返回了,从而接受不到响应数据包。所以这时就要设置超时时间,如果该socket超时之后仍然没有数据包到来,那么就直接返回。

设置socket超时时间的两种方式:

1、比较简洁的方式:利用setsockopt的SO_RCVTIMEO选项

#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int main()
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("fait to create socket\n");
return -1;
}
struct timeval timeout_val;
timeout_val.tv_sec = 5;  // 超时时间
timeout_val.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_val, sizeof(timeout_val))
< 0) {
printf("socket option  SO_RCVTIMEO not support\n");
return -1;
}
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(2222);

char buf[1024] = "aaaaaaaaaa";
if (sendto(fd, buf, strlen(buf) , 0, (struct sockaddr*)&server_addr,
sizeof(server_addr)) < 0) {
printf("fail to sendto\n");
return -1;
}
sockaddr_in peer_addr;
socklen_t addr_len = sizeof(peer_addr);
int recv_len = 0;
bzero(buf, sizeof(buf));
time_t start_time = time(NULL);
recv_len = recvfrom(fd, buf, sizeof(buf), 0,
reinterpret_cast<sockaddr*>(&peer_addr),
&addr_len);
printf("time_out=%d\n", time(NULL) - start_time);
if (errno == EWOULDBLOCK || errno== EAGAIN)
printf("recvfrom timeout\n");
else
printf("recvfrom err:%d\n", recv_len);
return 0;
}


2、稍微复杂的方式:利用select

#include <iostream>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int main()
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
printf("fait to create socket\n");
return -1;
}
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(2222);

char buf[1024] = "aaaaaaaaaa";
if (sendto(fd, buf, strlen(buf) , 0, (struct sockaddr*)&server_addr, sizeof(server_addr))
< 0) {
printf("fail to sendto\n");
return -1;
}
sockaddr_in peer_addr;
socklen_t addr_len = sizeof(peer_addr);
int recv_len = 0;
bzero(buf, sizeof(buf));

fd_set reasfds;
FD_ZERO(&reasfds);
FD_SET(fd, &reasfds);
struct timeval timeout_val;
timeout_val.tv_sec = 5;
timeout_val.tv_usec = 0;
int ret = select(fd+1, &reasfds, NULL, NULL, &timeout_val);
if (ret > 0) {
recv_len = recvfrom(fd, buf, sizeof(buf), 0,
reinterpret_cast<sockaddr*>(&peer_addr),
&addr_len);
if (recv_len < 0)
printf("recvfrom err, errno=%d\n", errno);
} else if (ret == 0) {
printf("recvfrom timeout\n");
} else {
printf("select err, errno=%d\n", errno);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  socket 网络 超时