socket编程的细节问题

What is the difference between AF_INET and PF_INET in socket programming?

In some documentation, you'll see mention of a mystical "PF_INET". This is a weird etherial beast that is rarely seen in nature, but I might as well clarify it a bit here. Once a long time ago, it was thought that maybe a address family (what the "AF" in "AF_INET" stands for) might support several protocols that were referenced by their protocol family (what the "PF" in "PF_INET" stands for).
That didn't happen. Oh well. So the correct thing to do is to use AF_INET in your struct sockaddr_in and PF_INET in your call to socket(). But practically speaking, you can use AF_INET everywhere. And, since that's what W. Richard Stevens does in his book, that's what I'll do here.

linux客户端Socket非阻塞connect编程

You have a non-blocking socket and you are calling connect() in it. Since connect() needs the 3-way handshake to happen (so a network roundtrip), it either blocks waiting for the SYN-ACK in blocking sockets, or gives you some indication that it hasn't succeded yet in non-blocking sockets. Normally, non-blocking sockets return EAGAIN/EWOULDBLOCK to tell you that they couldn't progress and you should try again: this is not exactly your case, connect() returns EAGAIN/EWOULDBLOCK when there are no free ephemeral ports to tell you that you should try again later; so there is another error for non-blocking connect: EINPROGRESS, which tells you that the operation is in progress and you should check its status later.

To check the status later, the socket will become ready for writability, so you can useselect()/poll()/... to test for that, after which you'll have to getsockopt(...SO_ERROR...)to get the success/failure status of your connect() operation.

int tcp_connect(const char *addr, int port, int timeout)
{
	int fd, error, tmp;
	unsigned int len;
	struct sockaddr_in sa_in;
	struct timeval tv;
	fd_set fds;

	if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
		return -1;
	bzero(&sa_in, sizeof(sa_in));
	sa_in.sin_family = AF_INET;
	sa_in.sin_port = htons(port);
	sa_in.sin_addr.s_addr = inet_addr(addr);
	set_nonblocking(fd, 1);
	PRINTF("Connect IP: %s PORT: %d(tcp_client)\n", addr, port, timeout);
	tmp = connect(fd, (struct sockaddr *)&sa_in, sizeof(sa_in));
	if (tmp < 0) {
		error = errno;
		if (error != EINTR && error != EINPROGRESS) {
			close(fd);
			PRINTF("Connect fail reason:%s(tcp_client)\n",
			    strerror(error));
			return -1;
		}
	}
	while (timeout > 0) {
		tv.tv_sec = 0;
		tv.tv_usec = 0;
		FD_ZERO(&fds);
		FD_SET(fd, &fds);
		tmp = select(fd + 1, NULL, &fds, NULL, &tv);
		if (tmp > 0) {
			len = sizeof(error);
			if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0
				|| error) {
				close(fd);
				PRINTF("Connect fail reason:%s(tcp_client)\n",
					strerror(error));
				return -1;
			}
			else {
				set_nonblocking(fd, 0);
				PRINTF("Connect ok, fd is %d\n", fd);
				return fd;
			}
		}
		else if (tmp < 0) {
			error = errno;
			if (error != EINTR && error != EINPROGRESS) {
				close(fd);
				PRINTF("Connect fail, reason:%s(tcp_client)\n",
					strerror(error));
				return -1;
			}
		}
		msleep(100);
		timeout -= 100;
	}
	close(fd);
	PRINTF("Connect timeout(tcp_client)\n");
	return -1;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值