关闭

socket编程的细节问题

466人阅读 评论(0) 收藏 举报
分类:

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;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:161822次
    • 积分:2616
    • 等级:
    • 排名:第14448名
    • 原创:87篇
    • 转载:97篇
    • 译文:0篇
    • 评论:26条
    文章分类
    最新评论