C:套接字连接超时
我有一个简单的程序来检查端口是否打开,但是我想缩短套接字连接的超时长度,因为默认值太长了。但我不知道该怎么做。代码如下:C:套接字连接超时,c,network-programming,C,Network Programming,我有一个简单的程序来检查端口是否打开,但是我想缩短套接字连接的超时长度,因为默认值太长了。但我不知道该怎么做。代码如下: #include <sys/socket.h> #include <sys/time.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <errno.h> #include <fcntl
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
u_short port; /* user specified port number */
char addr[1023]; /* will be a copy of the address entered by u */
struct sockaddr_in address; /* the libc network address data structure */
short int sock = -1; /* file descriptor for the network socket */
if (argc != 3) {
fprintf(stderr, "Usage %s <port_num> <address>", argv[0]);
return EXIT_FAILURE;
}
address.sin_addr.s_addr = inet_addr(argv[2]); /* assign the address */
address.sin_port = htons(atoi(argv[2])); /* translate int2port num */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (connect(sock,(struct sockaddr *)&address,sizeof(address)) == 0) {
printf("%i is open\n", port);
}
close(sock);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
u_短端口;/*用户指定的端口号*/
char addr[1023];/*将是u输入的地址的副本*/
地址中的struct sockaddr_;/*libc网络地址数据结构*/
网络套接字的short int sock=-1;/*文件描述符*/
如果(argc!=3){
fprintf(标准,“使用率%s”,argv[0]);
返回退出失败;
}
address.sin_addr.s_addr=inet_addr(argv[2]);/*分配地址*/
address.sin_port=htons(atoi(argv[2]);/*translate int2port num*/
sock=socket(AF\u INET,sock\u STREAM,0);
if(connect(sock,(struct sockaddr*)和address,sizeof(address))==0){
printf(“%i打开\n”,端口);
}
关闭(袜子);
返回0;
}
本文可能有助于:
看起来您将套接字置于非阻塞模式,直到连接完成,然后在连接建立后将其重新置于阻塞模式
void连接到(void){
国际关系;
地址中的结构sockaddr\u;
长精氨酸;
fd_集myset;
结构时间值电视;
int valopt;
socklen_t lon;
//创建套接字
soc=套接字(AF_INET,SOCK_STREAM,0);
如果(soc<0){
fprintf(stderr,“创建套接字(%d%s)时出错)\n”,errno,strerror(errno));
出口(0);
}
addr.sin_family=AF_INET;
地址:sin_port=htons(2000年);
addr.sin_addr.s_addr=inet_addr(“192.168.0.1”);
//设置非阻塞
如果((arg=fcntl(soc,F_GETFL,NULL))<0){
fprintf(标准,“错误fcntl(…,F_GETFL)(%s)\n”,strerror(errno));
出口(0);
}
arg |=O|u非块;
如果(fcntl(soc,F_SETFL,arg)<0){
fprintf(标准,“错误fcntl(…,F_SETFL)(%s)\n”,strerror(errno));
出口(0);
}
//正在尝试连接超时
res=connect(soc,(struct sockaddr*)和addr,sizeof(addr));
如果(res<0){
如果(errno==EINPROGRESS){
fprintf(stderr,“EINPROGRESS in connect()-selection\n”);
做{
tv.tv_sec=15;
tv.tv_usec=0;
FD_ZERO(&myset);
FD_集(soc和myset);
res=选择(soc+1、NULL和myset、NULL和tv);
如果(res<0&&errno!=EINTR){
fprintf(stderr,“连接%d-%s时出错”,errno,strerror(errno));
出口(0);
}
如果(res>0){
//选择要写入的套接字
lon=sizeof(int);
if(getsockopt(soc,SOL_SOCKET,SO_ERROR,(void*)(&valopt),&lon)<0{
fprintf(stderr,“getsockopt()中的错误%d-%s\n”,errno,strerror(errno));
出口(0);
}
//检查返回的值。。。
if(valopt){
fprintf(stderr,“延迟连接中的错误()%d-%s\n”,valopt,strerror(valopt)
);
出口(0);
}
打破
}
否则{
fprintf(stderr,“选择中超时()-取消!\n”);
出口(0);
}
}而(1),;
}
否则{
fprintf(stderr,“连接%d-%s时出错”,errno,strerror(errno));
出口(0);
}
}
//再次设置为阻塞模式。。。
如果((arg=fcntl(soc,F_GETFL,NULL))<0){
fprintf(标准,“错误fcntl(…,F_GETFL)(%s)\n”,strerror(errno));
出口(0);
}
arg&=(~O_非块);
如果(fcntl(soc,F_SETFL,arg)<0){
fprintf(标准,“错误fcntl(…,F_SETFL)(%s)\n”,strerror(errno));
出口(0);
}
//我希望就这些
}
将套接字设置为非阻塞,并使用select()
(它接受一个超时参数)。如果非阻塞套接字正在尝试连接,则select()
将在connect()
完成时(成功或失败)指示套接字可写。然后使用getsockopt()
确定connect()
的结果:
int main(int argc,char**argv){
u_短端口;/*用户指定的端口号*/
char*addr;/*将是指向地址的指针*/
地址中的struct sockaddr_;/*libc网络地址数据结构*/
网络套接字的short int sock=-1;/*文件描述符*/
fd_集fdset;
结构时间值电视;
如果(argc!=3){
fprintf(stderr,“用法%s\n”,argv[0]);
返回退出失败;
}
端口=atoi(argv[1]);
addr=argv[2];
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr(addr);/*分配地址*/
address.sin_port=htons(port);/*translate int2port num*/
sock=socket(AF\u INET,sock\u STREAM,0);
fcntl(承插式、固定式、非阻塞式);
连接(sock,(struct sockaddr*)和地址,sizeof(address));
FD_零点(&fdset);
FD_套装(袜子和FD套装);
tv.tv_sec=10;/*10秒超时*/
tv.tv_usec=0;
如果(选择(sock+1、NULL和fdset、NULL和tv)==1)
{
int-so_误差;
socklen_t len=so_错误的大小;
getsockopt(sock、SOL_SOCKET、SO_ERROR、&SO_ERROR、&len);
if(so_error==0){
printf(“%s:%d已打开\n”,地址,端口);
}
}
关闭(袜子);
返回0;
}
此选项已参数化ip、端口、超时(以秒为单位)、处理连接错误并为您提供以毫秒为单位的连接时间:
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int main(int argc, char **argv) {
struct sockaddr_in addr_s;
char *addr;
short int fd=-1;
int port;
fd_set fdset;
struct timeval tv;
int rc;
int so_error;
socklen_t len;
struct timespec tstart={0,0}, tend={0,0};
int seconds;
if (argc != 4) {
fprintf(stderr, "Usage: %s <ip> <port> <timeout_seconds>\n", argv[0]);
return 1;
}
addr = argv[1];
port = atoi(argv[2]);
seconds = atoi(argv[3]);
addr_s.sin_family = AF_INET; // utilizzo IPv4
addr_s.sin_addr.s_addr = inet_addr(addr);
addr_s.sin_port = htons(port);
clock_gettime(CLOCK_MONOTONIC, &tstart);
fd = socket(AF_INET, SOCK_STREAM, 0);
fcntl(fd, F_SETFL, O_NONBLOCK); // setup non blocking socket
// make the connection
rc = connect(fd, (struct sockaddr *)&addr_s, sizeof(addr_s));
if ((rc == -1) && (errno != EINPROGRESS)) {
fprintf(stderr, "Error: %s\n", strerror(errno));
close(fd);
return 1;
}
if (rc == 0) {
// connection has succeeded immediately
clock_gettime(CLOCK_MONOTONIC, &tend);
printf("socket %s:%d connected. It took %.5f seconds\n",
addr, port, (((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)));
close(fd);
return 0;
} /*else {
// connection attempt is in progress
} */
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = seconds;
tv.tv_usec = 0;
rc = select(fd + 1, NULL, &fdset, NULL, &tv);
switch(rc) {
case 1: // data to read
len = sizeof(so_error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error == 0) {
clock_gettime(CLOCK_MONOTONIC, &tend);
printf("socket %s:%d connected. It took %.5f seconds\n",
addr, port, (((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)));
close(fd);
return 0;
} else { // error
printf("socket %s:%d NOT connected: %s\n", addr, port, strerror(so_error));
}
break;
case 0: //timeout
fprintf(stderr, "connection timeout trying to connect to %s:%d\n", addr, port);
break;
}
close(fd);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
str
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int main(int argc, char **argv) {
struct sockaddr_in addr_s;
char *addr;
short int fd=-1;
int port;
fd_set fdset;
struct timeval tv;
int rc;
int so_error;
socklen_t len;
struct timespec tstart={0,0}, tend={0,0};
int seconds;
if (argc != 4) {
fprintf(stderr, "Usage: %s <ip> <port> <timeout_seconds>\n", argv[0]);
return 1;
}
addr = argv[1];
port = atoi(argv[2]);
seconds = atoi(argv[3]);
addr_s.sin_family = AF_INET; // utilizzo IPv4
addr_s.sin_addr.s_addr = inet_addr(addr);
addr_s.sin_port = htons(port);
clock_gettime(CLOCK_MONOTONIC, &tstart);
fd = socket(AF_INET, SOCK_STREAM, 0);
fcntl(fd, F_SETFL, O_NONBLOCK); // setup non blocking socket
// make the connection
rc = connect(fd, (struct sockaddr *)&addr_s, sizeof(addr_s));
if ((rc == -1) && (errno != EINPROGRESS)) {
fprintf(stderr, "Error: %s\n", strerror(errno));
close(fd);
return 1;
}
if (rc == 0) {
// connection has succeeded immediately
clock_gettime(CLOCK_MONOTONIC, &tend);
printf("socket %s:%d connected. It took %.5f seconds\n",
addr, port, (((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)));
close(fd);
return 0;
} /*else {
// connection attempt is in progress
} */
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
tv.tv_sec = seconds;
tv.tv_usec = 0;
rc = select(fd + 1, NULL, &fdset, NULL, &tv);
switch(rc) {
case 1: // data to read
len = sizeof(so_error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error == 0) {
clock_gettime(CLOCK_MONOTONIC, &tend);
printf("socket %s:%d connected. It took %.5f seconds\n",
addr, port, (((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)));
close(fd);
return 0;
} else { // error
printf("socket %s:%d NOT connected: %s\n", addr, port, strerror(so_error));
}
break;
case 0: //timeout
fprintf(stderr, "connection timeout trying to connect to %s:%d\n", addr, port);
break;
}
close(fd);
return 0;
}
int synRetries = 2; // Send a total of 3 SYN packets => Timeout ~7s
setsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &synRetries, sizeof(synRetries));
struct timeval timeout;
timeout.tv_sec = 7; // after 7 seconds connect() will timeout
timeout.tv_usec = 0;
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
connect(...)
// Compilation error
setsockopt(fd, SO_SNDTIMEO, &timeout, sizeof(timeout));
// Fixed?
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
struct timeval timeout;
timeout.tv_sec = 7; // after 7 seconds connect() will timeout
timeout.tv_usec = 0;
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
connect(...)
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<signal.h>
#include<errno.h>
static void signal_handler(int signo)
{
return; // Do nothing just interrupt.
}
int main()
{
/* Register signal handler */
struct sigaction act, oact;
act.sa_handler = signal_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
if(sigaction(SIGALRM, &act, &oact) < 0) // Error registering signal handler.
{
fprintf(stderr, "Error registering signal disposition\n");
exit(1);
}
/* Prepare your socket and sockaddr structures */
int sockfd;
struct sockaddr* servaddr;
/* Implementing timeout connect */
int sec = 30;
if(alarm(sec) != 0)
fprintf(stderr, "Already timer was set\n");
if(connect(sockfd, servaddr, sizeof(struct sockaddr)) < 0)
{
if(errno == EINTR)
fprintf(stderr, "Connect timeout\n");
else
fprintf(stderr, "Connect failed\n");
close(sockfd);
exit(1);
}
alarm(0); /* turn off the alarm */
sigaction(SIGALRM, &oact, NULL); /* Restore the default actions of SIGALRM */
/* Use socket */
/* End program */
close(sockfd);
return 0;
}
/* All the code stays */
/* Modifications at connect */
int conn_ret = connect(sockfd, servaddr, sizeof(struct sockdaddr));
if(conn_ret == 0)
goto done;
/* Modifications at select */
int sec = 30;
for( ; ; )
{
struct timeval timeo;
timeo.tv_sec = sec;
timeo.tv_usec = 0;
fd_set wr_set, rd_set;
FDZERO(&wr_set);
FD_SET(sockfd, &wr_set);
rd_set = wr_set;
int sl_ret = select(sockfd + 1, &rd_set, &wr_set, NULL, &timeo);
/* All the code stays */
}
done:
/* Use your socket */
#include <sys/socket.h>
#include <fcntl.h>
#include <poll.h>
#include <time.h>
int connect_with_timeout(int sockfd, const struct sockaddr *addr, socklen_t addrlen, unsigned int timeout_ms) {
int rc = 0;
// Set O_NONBLOCK
int sockfd_flags_before;
if((sockfd_flags_before=fcntl(sockfd,F_GETFL,0)<0)) return -1;
if(fcntl(sockfd,F_SETFL,sockfd_flags_before | O_NONBLOCK)<0) return -1;
// Start connecting (asynchronously)
do {
if (connect(sockfd, addr, addrlen)<0) {
// Did connect return an error? If so, we'll fail.
if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
rc = -1;
}
// Otherwise, we'll wait for it to complete.
else {
// Set a deadline timestamp 'timeout' ms from now (needed b/c poll can be interrupted)
struct timespec now;
if(clock_gettime(CLOCK_MONOTONIC, &now)<0) { rc=-1; break; }
struct timespec deadline = { .tv_sec = now.tv_sec,
.tv_nsec = now.tv_nsec + timeout_ms*1000000l};
// Wait for the connection to complete.
do {
// Calculate how long until the deadline
if(clock_gettime(CLOCK_MONOTONIC, &now)<0) { rc=-1; break; }
int ms_until_deadline = (int)( (deadline.tv_sec - now.tv_sec)*1000l
+ (deadline.tv_nsec - now.tv_nsec)/1000000l);
if(ms_until_deadline<0) { rc=0; break; }
// Wait for connect to complete (or for the timeout deadline)
struct pollfd pfds[] = { { .fd = sockfd, .events = POLLOUT } };
rc = poll(pfds, 1, ms_until_deadline);
// If poll 'succeeded', make sure it *really* succeeded
if(rc>0) {
int error = 0; socklen_t len = sizeof(error);
int retval = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
if(retval==0) errno = error;
if(error!=0) rc=-1;
}
}
// If poll was interrupted, try again.
while(rc==-1 && errno==EINTR);
// Did poll timeout? If so, fail.
if(rc==0) {
errno = ETIMEDOUT;
rc=-1;
}
}
}
} while(0);
// Restore original O_NONBLOCK state
if(fcntl(sockfd,F_SETFL,sockfd_flags_before)<0) return -1;
// Success
return rc;
}