时间获取程序客户端 TCP 使用非阻塞connect

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

/**

* TCP,使用非阻塞 connect

**/

#include "unp.h"

int

connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)

{

int flags, n, error;

socklen_t
len;

fd_set
rset, wset;

struct timeval
tval;

//1.调用 fcntl 设置套接字为非阻塞

flags = Fcntl(sockfd, F_GETFL, 0);

Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

//2.发起非阻塞连接

//期望的错误是 EINPROGRESS ,表示连接建立已经启动但尚未完成。

// n > 0 是什么情况

error = 0;

if ( (n = connect(sockfd, saptr, salen)) < 0)

if (errno != EINPROGRESS)

return(-1);

/*在连接建立期间,可以做其他事 */

//3.检查连接是否建立

// n == 0 表示连接已经建立(客户和服务器在同一台主机时,这种情况更有可能发生)

if (n == 0)

goto done;
/* 连接建立完毕 */

//4.调用 select

FD_ZERO(&rset);//清零 rset

FD_SET(sockfd, &rset); //打开 rset 中对应 sockfd 的位

wset = rset; //将 rset 复制到 wset

tval.tv_sec = nsec; //设置超时时间

tval.tv_usec = 0;

//调用 select 等待套接字变为可读或可写

if ( (n = Select(sockfd+1, &rset, &wset, NULL,

nsec ? &tval : NULL)) == 0) {

//处理超时,如果 select 返回 0,那么超时发生

close(sockfd);

errno = ETIMEDOUT;

return(-1);

}

//5.检查可读或可写条件

//如果套接字可写不可读,则连接建立成功

//如果套接字可写又可读,则可能 select 之前套接字已经建立成功,或连接建立失败

//如果套接字既不可写又不可读,则 select 出错,因为 sockfd 没有设置

if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {

len = sizeof(error);

//使用 getsockopt 取得套接字的待处理错误。如果连接成功建立,该值为 0.

if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)

return(-1);
/* Solaris pending error */

} else

err_quit("select error: sockfd not set");

//6.关闭非阻塞状态并返回

done:

Fcntl(sockfd, F_SETFL, flags);
//恢复套接字的文件状态标志并返回

if (error) {

close(sockfd);
/* just in case */

errno = error;

return(-1);

}

return(0);

}

#include    "unp.h"

int

main(int argc, char **argv)

{

int sockfd, n;

char recvline[MAXLINE + 1];

struct sockaddr_in
servaddr;

if (argc != 2)

err_quit("usage: a.out <IPaddress>");

if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)

err_sys("socket error");

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_port   = htons(13);

if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)

err_quit("inet_pton error for %s", argv[1]);

//这里从 connect 改为 connect_nonb

if (connect_nonb(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)

err_sys("connect error");

while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {

recvline[n] = 0;
/* null terminate */

if (fputs(recvline, stdout) == EOF)

err_sys("fputs error");

}

if (n < 0)

err_sys("read error");

exit(0);

}

时间: 2024-08-06 11:34:43

时间获取程序客户端 TCP 使用非阻塞connect的相关文章

UNIX网络编程卷1 时间获取程序client TCP 使用非堵塞connect

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.当在一个非堵塞的 TCP 套接字(可使用 fcntl 把套接字变成非堵塞的)上调用 connect时. connect 将马上返回一个 EINPROGRESS 错误,只是已经发起的 TCP 三路握手继续进行. 接着使用 select 检測 这个连接是否建立成功 2.用途: 1)在TCP三路握手的时候进行其它处理 2)同一时候建立多个连接 3)使用 select 设置超时 /** * T

时间获取程序客户端 TCP 协议相关性

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码: 这是一个简单的时间获取客户程序.客户与服务器建立一个TCP连接后,服务器以直观 可读格式简单地送回当前时间和日期 这个例子是协议相关,使用 inet_pton TCP/IPv4, IPv6 协议相关 IPv4 --> IPv6 (把代码中出现的左边的字符串换为右边的,就变成了IPv6版本的) sockaddr_in --> sockaddr_in6 AF_INET -->

时间获取程序服务器 TCP 协议相关性

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码: 这是一个简单的时间获取服务器程序.它和时间获取程序客户端一道工作. TCP/IPv4, IPv6 协议相关 IPv4 --> IPv6 (把代码中出现的左边的字符串换为右边的,就变成了IPv6版本的) sockaddr_in --> sockaddr_in6 AF_INET --> AF_INET6 sin_family --> sin6_family sin_p

UNIX网络编程卷1 时间获取程序server TCP 协议相关性

本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码: 这是一个简单的时间获取server程序.它和时间获取程序client一道工作. 它是 协议相关,把代码中出现的左边的字符串换为右边的,就变成了IPv6版本号的 IPv4 --> IPv6 sockaddr_in --> sockaddr_in6 AF_INET --> AF_INET6 sin_family --> sin6_family sin_port --&

TCP之非阻塞connect和accept

套接字的默认状态是阻塞的,这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待响应操作完成,可能阻塞的套接字调用可分为以下四类: (1) 输入操作,包括read,readv,recv,recvfrom,recvmsg: (2) 输出操作,包括write,writev,send,sendto,sendmsg: (3) 接受外来连接,即accept函数. (4) 发起外出连接,即tcp的connect函数: 非阻塞connect: 当一个非阻塞的tcp套接字上调用connect时

时间获取程序客户端 UDP 协议无关

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * UDP,协议无关,调用 getaddrinfo 和 udp_client **/ #include "unp.h" int udp_client(const char *host, const char *serv, SA **saptr, socklen_t *lenp) { int sockfd, n; struct addrinfo hints, *res, *

TCP非阻塞accept和非阻塞connect

http://blog.chinaunix.net/uid-20751538-id-238260.html 非阻塞accept 当一个已完成的连接准备好被accept的时候,select会把监听socket标记为可读.因此,如果用select等待外来的连接时,应该不需要 把监听socket设置为非阻塞模式,因为如果select告诉我们连接已经就绪,accept就不应该被阻塞.不过这样做的时候有一个BUG:当客户端 在跟服务器建立连接之后发送了一个RST包,这个时候accept就会阻塞,直到有下一

socket 客户端编程:非阻塞式连接,错误判断及退出重连

本文将探讨 socket 客户端的非阻塞式连接,连接成功后的错误判断及退出重连. 1. 连接方法 关于socket 客户端的非阻塞 connect 编程,网上找到的实现方式一般都是, 套接字创建之后,默认是阻塞式的,对其执行 connect 操作,如果服务端在监听,则会成功建立连接,但这只是理想情况.如果服务端没有开启,或是网络异常呢,connect 会一直阻塞到连接超时,这个超时时间在 Linux 下一般是 75 s 到几分钟.那么,如果在服务端未打开的时候 connect,连接建立会阻塞,即

面向连接的socket数据处理过程以及非阻塞connect问题

对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后必须调用bind绑定到一个指定的地址,然后调用int listen(int sockfd, int backlog);进行监听.此时服务器socket允许客户端进行连接,backlog提示没被accept的客户连接请求队列的大小,系统决定实际的值,最大值定义为SOMAXCONN在头文件<sys/so