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 设置超时

/**
* 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 表示连接已经建立(客户和server在同一台主机时,这样的情况更有可能发生)
	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-10-12 03:42:06

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

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

本文为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 t

《UNIX网络编程 卷1》之&quot;学习环境搭建&quot;(CentOS 7)

<UNIX网络编程 卷1>的源码可以从www.unpbook.com下载得到.解压之后的目录为unpv13e.  1. 编译 进入unpv13e目录,按如下步骤编译: 1 ./configure 2 3 cd lib 4 make // 可能遇到问题:redefinition of ‘struct in_pktinfo’ 5 6 cd ../libfree 7 make 8 9 cd ../libroute 10 make //这一步可能会出错,可忽略,只是表示你的系统不支持 4.4BSD,并

UNIX网络编程 卷2:进程间通信

这篇是计算机类的优质预售推荐>>>><UNIX网络编程 卷2:进程间通信(第2版)> UNIX和网络专家W. Richard Stevens的传世之作 编辑推荐 两卷本的<UNIX网络编程>是已故著名技术作家W. Richard Stevens的传世之作.卷2着重讨论怎样让应用程序与在其它机器上的应用程序进行对话. 良好的进程间通信(IPC)机制是提高UNIX程序性能的关键. 本书全面深入地解说了各种进程间通信形式,包括消息传递.同步.共享内存及远程过程调用

[转载] 读《UNIX网络编程 卷1:套接字联网API》

原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网络编程 卷1:套接字联网API>, 英文名叫Unix Network Programming啦,后来上网查了查, 一般都叫UNP逼格会高一点, 就像APUE一样. 他们的作者都是W. Richard Stevens. 另外,他也是TCP/IP Illustrated的作者. 靠,看完作者简介,简直崇拜得

Linux网络编程(简单的时间获取服务器)

1.一个简单的服务器时间获取程序 服务器和客户端采用UDP通信的方式,来编写一个简单的时间获取应用. 把过程大致理顺一下,首先是服务器端的编写,使用的是迭代的方式,没有并发 先创建一个socket而后bind服务器,绑定之后就可以创建一个循环来接收和发送 信息了,以达到和客户端之间的通信. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include

UNIX网络编程 卷1:套接字联网API

这篇是计算机类的优质预售推荐>>>><UNIX网络编程 卷1:套接字联网API> UNIX和网络专家W. Richard Stevens的传世之作,世界著名网络专家Bill Fenner和Andrew M. Rudoff执笔新版 编辑推荐 这是一部传世之作!顶级网络编程专家Bill Fenner和Andrew M. Rudoff应邀执笔,对W. Richard Stevens的经典作品进行修订.书中吸纳了近几年网络技术的发展,增添了IPv6.SCTP协议和密钥管理套接字

将UNIX网络编程卷2的库函数合并到卷1的库函数中

源起 前面讲述了unix网路编程卷1库函数的配置.但是卷2还有一个配置,而且其中的关于进程间通信的函数在卷1中也没有. 我们使用两个库函数不免有些不方便,现在将卷2中的在卷1中没有的函数都合并到卷1的库函数中. 1.创建unix网络编程卷2——进程间通信configure.h配置文件    cd 目录    ./configure    之后创建了configure.h文件. 2.合并unix网路编程卷1和卷2的configure.h文件    将上面生成的configure.h的头文件的宏定义

UNIX网络编程卷2 源码编译篇

W. Richard Stevens的主页: 源代码下载   >>  ~/Downloads/unpv22e.tar.gz; 1 tar -xzfv unpv22e.tar.gz 2 cd unpv22e 3 ./configure 4 cd lib 5 make make编译失败,因为需要对两个文件修改,unpv22e/config.h和unpv22e/wrapunix.c. 1 vi config.h 2 3 /*注释掉这三行*/ 4 // #define uint8_t unsigned