socket设定连接超时如何设置?

icewolf_li 2005-04-05 11:10:18
java里面是setSoTimeout()就可以设定socket连接的连接响应超时,
请问C里面如何做?好像如果用select方法有个timeout参数,但如果我不用select怎么办?
本人C不熟,各位指点一下了。
最好告知windows和unix下的方法,或者函数名。
...全文
652 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
icewolf_li 2005-04-11
  • 打赏
  • 举报
回复
ok.大致明白了。先揭帖。
tcprince 2005-04-10
  • 打赏
  • 举报
回复
为什么要不用select()呢?难道就因为不熟吗?不用怎么熟?
zhousqy 2005-04-10
  • 打赏
  • 举报
回复
up
wtogether 2005-04-10
  • 打赏
  • 举报
回复
那个扩展的xnet_select函数是通用的,在不同的OS下用不同的头文件而已,win32和unix下都可以用
用的时候这么用:
if (xnet_select(fd, 0, 500, WRITE_STATUS)>0) write(fd, buf, strlen(buf));

/* display the server response */
printf("Server response:\n");
while (xnet_select(fd, 3, 0, READ_STATUS)>0)
{
if ((n=read(fd, buf, BUFSIZE))==-1) break;
buf[n] = '\0';
printf("%s\n", buf);
}
ghostsG 2005-04-10
  • 打赏
  • 举报
回复
up.我也想知道
yeehya 2005-04-08
  • 打赏
  • 举报
回复
cnman(不明) ---UNIX下一般是通过SIGNAL设置的超时信号实现。
__________________________________________________________
严重同意!
可以这样:
global_v: int connflag = 0;
in main:
{
signal(SIGALRM, alarm_handler);//对由alarm产生的SIGALRM信号设定自己定义的处理函数.
alarm(Time_YouWant);
if(connect ()>=0)
connflag = 1;
else
//error handle!
}
in alarm_handler:
{
if(connflag) //ok!
//just return to main!
else //timeout
//do someting before exit()!
}
不知道这样可不可以,也是初学,:-)
icewolf_li 2005-04-08
  • 打赏
  • 举报
回复
wtogether(wtogether) :
这是unix下的实现方式?

下面是简单的socket连接。要怎么改?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#ifdef WIN32
#include <winsock2.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#define MAX_STRING_LEN 2048
#define BUFSIZE 1024

char hostname[MAX_STRING_LEN];
char buf[BUFSIZE];

static char i_host[MAX_STRING_LEN]; /* site name the web cache sitting in */
static char i_port[MAX_STRING_LEN]; /* port number invalidator listens on */
static char i_pass[MAX_STRING_LEN]; /* password of user invalidator */
static char i_uriprefix[MAX_STRING_LEN]; /* Specify the prefix path of the documents to be invalidated. The prefix path must begin with http|https://host_name:port/path/filename or "/" and end with "/". */
static char i_uri[MAX_STRING_LEN]; /* Specify the URL of the documents to be invalidated underneath the URIPREFIX */
static int i_verbose = 1;

char http_POST[] = "POST /x-oracle-cache-invalidate HTTP/1.0\r\n";
char http_ContentLength[BUFSIZE];
char http_Authorization[MAX_STRING_LEN];

void err_doit(int errnoflag, const char *fmt, va_list ap);
void err_quit(const char *fmt, ...);
int tcp_connect(const char *host, const unsigned short port);
void print_usage();

int tcp_connect(const char *host, const unsigned short port)
{
char * transport = "tcp";
struct hostent *phe; /* pointer to host information entry */
struct protoent *ppe; /* pointer to protocol information entry*/
struct sockaddr_in sin; /* an Internet endpoint address */
int s; /* socket descriptor and socket type */

#ifdef WIN32
{
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 0 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
/* Tell the user that we couldn't find a usable */
/* WinSock DLL. */
printf("can't initialize socket library\n");
exit(0);
}
}
#endif

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;

if ((sin.sin_port = htons(port)) == 0)
err_quit("invalid port \"%d\"\n", port);

/* Map host name to IP address, allowing for dotted decimal */
if ( phe = gethostbyname(host) )
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE )
err_quit("can't get \"%s\" host entry\n", host);

/* Map transport protocol name to protocol number */
if ( (ppe = getprotobyname(transport)) == 0)
err_quit("can't get \"%s\" protocol entry\n", transport);

/* Allocate a socket */
s = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
if (s < 0)
err_quit("can't create socket: %s\n", strerror(errno));

/* Connect the socket */
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
err_quit("can't connect to %s:%d\n", host, port);
return s;
}

void err_doit(int errnoflag, const char *fmt, va_list ap)
{
int errno_save;
char buf[MAX_STRING_LEN];

errno_save = errno;
vsprintf(buf, fmt, ap);
if (errnoflag)
sprintf(buf + strlen(buf), ": %s", strerror(errno_save));
strcat(buf, "\n");
fflush(stdout);
fputs(buf, stderr);
fflush(NULL);
return;
}

/* Print a message and terminate. */
void err_quit(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(0, fmt, ap);
va_end(ap);
exit(1);
}

#ifdef WIN32
char *optarg;

char getopt(int c, char *v[], char *opts)
{
static int now = 1;
char *p;

if (now >= c) return EOF;

if (v[now][0] == '-' && (p = strchr(opts, v[now][1]))) {
optarg = v[now+1];
now +=2;
return *p;
}

return EOF;
}

#else
extern char *optarg;
#endif

#define required(a) if (!a) { return -1; }

int init(int argc, char *argv[])
{
char c;
int i,optlen;
int slashcnt;

i_host[0] = '\0';
i_port[0] = '\0';

//printf("%d\n%s\n",argc,argv[7]);
while ((c = getopt(argc, argv, "h:p:?")) != EOF) {
//printf("%c\n",c);
if (c == '?')
return -1;
switch (c) {
case 'h':
required(optarg);
strcpy(i_host, optarg);
break;
case 'p':
required(optarg);
strcpy(i_port, optarg);
break;
default:
return -1;
}
}

/*
* there is no default value for hostname, port number,
* password or uri
*/
if (i_host[0] == '\0' || i_port[0] == '\0')
return -1;

return 1;
}

void print_usage()
{
char *usage[] =
{
"Usage:",
" -h host name",
" -p port",
"example:",
" -h 127.0.0.1 -p 4001",
};
int i;

for (i = 0; i < sizeof(usage) / sizeof(char*); i++)
printf("%s\n", usage[i]);

return;
}

#ifdef WIN32
#define write(a, b, c) send(a, b, c, 0)
#define read(a, b, c) recv(a, b, c, 0)
#endif

int main(int argc, char *argv[])
{
int fd;
int n;

/* parse command line etc ... */
if (init(argc, argv) < 0) {
print_usage();
exit(1);
}

buf[0] = '\0';

/* pack the info into the buffer */
strcpy(buf, "HelloWorld");

/* make connection to the server */
fd = tcp_connect(i_host, (unsigned short)atoi(i_port));

/* send off the message */
write(fd, buf, strlen(buf));

/* display the server response */
printf("Server response:\n");
n = read(fd, buf, BUFSIZE);
buf[n] = '\0';
printf("%s\n", buf);


#ifdef WIN32
WSACleanup();
#endif

return 0;
}
wtogether 2005-04-08
  • 打赏
  • 举报
回复
//xnet_select x defines
#define READ_STATUS 0
#define WRITE_STATUS 1
#define EXCPT_STATUS 2

/*
s - SOCKET
sec - timeout seconds
usec - timeout microseconds
x - select status
*/
int xnet_select(SOCKET s, DWORD sec, DWORD usec, BYTE x)
{
int st = SOCKET_ERROR;
struct timeval to;
fd_set fs;
to.tv_sec = sec;
to.tv_usec = usec;
FD_ZERO(&fs);
FD_SET(s, &fs);
switch(x)
{
case READ_STATUS:
st = select(s+1, &fs, 0, 0, &to);
break;
case WRITE_STATUS:
st = select(s+1, 0, &fs, 0, &to);
break;
case EXCPT_STATUS:
st = select(s+1, 0, 0, &fs, &to);
break;
}
return(st);
}
yeehya 2005-04-07
  • 打赏
  • 举报
回复
帮顶一下~~~
期待答案
yeehya 2005-04-07
  • 打赏
  • 举报
回复
这个超时的时间是不是由相关协议来确定的吧~
难道要修改协议中的某些值~?
ghostsG 2005-04-07
  • 打赏
  • 举报
回复
up
icewolf_li 2005-04-07
  • 打赏
  • 举报
回复
connect的超时呢?unix下呢?
suyun9329 2005-04-07
  • 打赏
  • 举报
回复
up
liuleilover 2005-04-07
  • 打赏
  • 举报
回复
一般在socket创建后就可以用setsockopt设置Recv/Send超时,而且在任何时候修改。
如果想设置Connect/Accept超时只能用Select实现
cnman 2005-04-07
  • 打赏
  • 举报
回复
UNIX下一般是通过SIGNAL设置的超时信号实现。
cc1q 2005-04-07
  • 打赏
  • 举报
回复
帮顶一下~~~
MagicCarmack 2005-04-06
  • 打赏
  • 举报
回复
MSDN
晨星 2005-04-05
  • 打赏
  • 举报
回复
关于sotsockopt的用法,可以查MSDN。
晨星 2005-04-05
  • 打赏
  • 举报
回复
只知道windows socket2库中可以使用setsockopt设置同步socket的发送和接收消息的超时时间。

如:
socket sock;
……
……
int iSendTime = 5000;//5秒
int iRecvTime = 5000;
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&iSendTime, sizeof(iSendTime));
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&iRecvTime, sizeof(iRecvTime));
结构层次及相互联系 (1)、工作线程:响应连接的IO投递返回并负责投递读请求,并将IO返回结果投递给处理线程,可设定参数决定工作线程数量; (2)、处理线程:处理线程调用回调函数将信息传递给应用层或协议栈,可设定参数决定工作处理数量; (3)、看守线程:响应Accept事件调用AcceptEx,检测连接和心跳超时 ,将信息投递给工作线程,模块仅有一个看守线程。 1. 技术要求 (1)、线程同步:Lock指令、临界段; (2)、主要Socket API:WSASend、WSARecv、AcceptEx、DisconnectEx; (3)、内存管理:连接池(句柄重用)、内存池; (4)、数据0拷贝:通过内置处理线程,上层应用可以避免自建线程池及复制数据的过程。同时提供GBuf内存分配功能,应用层获得分配地址及填充数据之后亦可直接投递给内核/驱动层; (5)、数据顺序同步:同一个连接同时只有一个处理线程响应其IO事件; (6)、IO请求投递:单投递读、多投递写; (7)、0缓冲读投递:可条件编译实现,以适用大规模连接要求。 (8)、超时机制:可设置连接连接不发送数据)超时时间以防止DOS攻击,也可设置心跳超时时间防止网络故障导致的现有连接成为虚连接避免耗尽系统资源。 (9)、接口技术:API、回调函数、客户句柄(客户连接句柄)。 (10)、主、被动发送:不使用HASH、MAP及LIST技术,即可提供安全可靠高效的客户连接句柄,以实现服务器端主被动发送数据功能; (11)、PerHandleData的回收不以IO投递的计数器或链表来做依据但仍能安全回收,同时尽量避免在高频的读写操作时做其他无关的操作以提高读写效率。 (12)、处理线程和工作线程有着良好分工界限,繁重的工作交给处理线程完成,工作线程工作量最大限度的减少,仅响应投递返回及读投递的操作; (13)、支持AWE,模块自动识别AWE是否开启(需手动开启),“否”则使用虚拟内存机制。 2. 功能要求 (1)、多IP多端口监听,每个监听可设置不同的回调函数,以高效的区别处理数据 (2)、可设置每秒最大的连接并发量和空连接连接不发数据)超时时间以防止DOS攻击造成的服务瘫痪、具有心跳处理(防网络异常造成的虚连接)功能 (3)、不加协议的透明传输,可适用广泛的网络通讯环境 (4)、可现实主、被动发送数据,但不会因兼顾主动发送而额外增加降低效率的工作 (5)、内置处理线程,上层应用可不必自建线程池处理数据,所有IO事件按顺序调用回调函数并可以在回调函数内直接处理数据,不必担心多线程造成的接收数据乱序的问题。 (6)、高效率的数据对应关联机制,在初次连接并根据登录数据设置每个连接对应的宿主(Owner)之后,再接收的数据即可立即获得该连接对应的宿主,而不必再做额外的查询工作,并且模块内部采用的是指针关联方式,对于长连接、主动发送的服务器系统而言是高效率的。 (7)、可兼容IPv6 3. 注意事项 因硬件环境和应用环境不同,不合理的配置会出现效率及性能上的问题,因此以下情况出现时,请务必与作者联系以确保获得更好的参数配置: (1)、连接量超过1000个的。超过的应结合具体硬件配置和网络带宽等因素综合设定运行参数。 (2)、带宽使用率超过20%的。工作线程和处理线程数量的设置也是综合考虑数据吞吐量和数据处理负载的因素来设置的,过多的线程会在调度上浪费时间,同时也应该综合考虑线程优先级别来设置工作线程和处理线程数量,两者的设置也不一定能相等。 (3)、服务器端有主动发送需求的、短连接(含网络故障造成的连接断开)出现频率高的。 压力测试工具介绍: 一、 使用G-TcpClient模块 二、 可以设定间隔时间发起大规模长、短连接 三、 可以发起密集数据包,包括即时和定时发送,1M的光纤带宽最大可以达到100K/S(单向)以上,100M本地网最大可以达到10M/S(单向)以上 四、 数据发送仅由一个独立线程但当,每点击一次Connect就创建一个线程根据当前参数发起连接。 五、 测试前提:服务器接收客户端数据后立即原样返回给客户端

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧