Linux-socket编程之非阻塞tcp程序示例和UDP程序示例

目录

1、TCP通讯

2、UDP通讯


1、TCP通讯

tcp是可靠通讯,需要先建立连接,再发送数据。

connect阻塞模式下,一般是默认75s,但是因为有线程切换等原因,实际时间会更长。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

#include 
#include 
#include 

#define PEER_IP     "192.168.2.104"
#define PEER_PORT   502

int main()
{
	 int ret = 0;
	 int sock_fd;
	 int flags=0;
	 struct sockaddr_in addr;

	 sock_fd = socket(AF_INET, SOCK_STREAM, 0);

	 fcntl(sock_fd, F_SETFL, flags|O_NONBLOCK);

	 addr.sin_family  = AF_INET;
	 addr.sin_port  = htons(PEER_PORT);
	 addr.sin_addr.s_addr = inet_addr(PEER_IP);
	 int res = connect(sock_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
	 if (0 == res)
	 {
		printf("socket connect succeed immediately.\n");
		ret = 0;
	 }
	 else
	 {
		if (errno == EINPROGRESS)
		{
			res = connect(sock_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
			if(0 == res)
			{
			   printf("socket connect succeed the second time.\n");
			   ret = 0;
			} else
			{
				printf("connect to host %s:%d failed.\n", PEER_IP, PEER_PORT);
				ret = errno;
			}
		}
	 }

	if (0 == ret)
    {
        send(sock_fd, "hello", sizeof("hello"), 0);
    }
    else
    {
        printf("connect to host %s:%d failed.\n", PEER_IP, PEER_PORT);
    }

	close(sock_fd);
	return ret;
}

这里注意一下:

就是客户端再connect的时候第一次connect总是会返回-1,errno是115,往往第二次连接就可以成功了。但是对于服务端来说,第一次连接已经成功返回了。这里可能跟设置socket是非阻塞的有关系。

解决方法:

1)先设置socket为阻塞,待connect连接成功后改成非阻塞

2)connect返回115时,需要判断socket是否可写,如果时可写的话则连接成功,通过select 或者poll判断可写

3)第一次connect返回EINPROGRESS可再次connect,如果没问题就证明成功 
 

Linux下常见的socket错误码:

EACCES, EPERM:用户试图在套接字广播标志没有设置的情况下连接广播地址或由于防火墙策略导致连接失败。

EADDRINUSE 98:Address already in use(本地地址处于使用状态)

EAFNOSUPPORT 97:Address family not supported by protocol(参数serv_add中的地址非合法地址)

EAGAIN:没有足够空闲的本地端口。

EALREADY 114:Operation already in progress(套接字为非阻塞套接字,并且原来的连接请求还未完成)

EBADF 77:File descriptor in bad state(非法的文件描述符)

ECONNREFUSED 111:Connection refused(远程地址并没有处于监听状态)

EFAULT:指向套接字结构体的地址非法。

EINPROGRESS 115:Operation now in progress(套接字为非阻塞套接字,且连接请求没有立即完成)

EINTR:系统调用的执行由于捕获中断而中止。

EISCONN 106:Transport endpoint is already connected(已经连接到该套接字)

ENETUNREACH 101:Network is unreachable(网络不可到达)

ENOTSOCK 88:Socket operation on non-socket(文件描述符不与套接字相关)

ETIMEDOUT 110:Connection timed out(连接超时)
 

2、UDP通讯

UDP是不可靠通讯,面向非连接的。

你可能感兴趣的:(Linux)