Linux网络通信------connect函数

#include <sys/types.h>; 
#include <sys/socket.h>;
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); 

在Linux中的socket编程中,建立网络连接是通过connect函数来完成的,函数原型为:
int connect (int sockfd, struct sockaddr * serv_addr, int addrlen)

  • sockfd:该参数是通过调用socket()函数来获得socket的文件描述符并传入该位置。
  • serv_addr:该参数是可传入的实际结构体为sockaddr_in和sockadd_in6
    • sockaddr_in:该结构体存有将要connect的ipv6的网络地址以及端口和协议族
    • sockaddr_in6:该结构体存有将要connect的ipv6的网络地址以及端口和协议族
  • addrlen: 为传入参数sockaddr结构体的大小,该参数实际应该是一个传出参数。

阻塞模式下connect的返回值和参数设置

  1. 首先,阻塞和非阻塞不是connect函数的属性。而是通过socket的函数获取的文件描述符所指向的抽象文件的属性。
  2. 所以需要通过操作socket获取的文件描述符fd(file descriptor)来对其设置为非阻塞,默认情况下,socket文件的属性为阻塞的。

接下来是获取一个阻塞的socket文件描述符

		//这里以ipv6的connect连接为例,ipv4可自行百度
		int fd = socket(AF_INET6,SOCK_STREAM,0);			//AF_INET:指定为ipv6协议族,SOCK_STREAM:面向流的连接,第三个为0就好,该参数是指定具体协议
		//由于默认的socket就是阻塞的,所以可以直接将该获取的fd加入到connect的第一个参数中。即完成了第一个参数的设置
	//通过一个ipv6的地址字符串和端口获取一个sockaddr_in6
	struct sockaddr_in6 addr6;		//定义一个sockaddr_in6
	addr6.sin6_family = AF_INET6;		//指定该sockaddr_in6的协议为ipv6协议
	addr6.sin6_port = htons(80);			//指定连接的端口,htons()函数是将一个本地字节序的short转为网络字节序的short
	inet_pton(AF_INET6, "::1", &amp;addr6.sin6_addr);		//指定连接的ipv6地址,inet_pton是将ipv6的地址字符串转为网络字节序传输的字符串
	//这样就完成了connect的第二个参数的设置
	
	//获取sockaddr_in6的长度
	int len = sizeof(sockaddr_in6);
	//即完成了第三个参数的设置

	//调用connect函数进行连接,即完成了整个过程: 连接成功flag返回0,连接失败flag返回-1
	int flag = connect(fd,&amp;addr6,len);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • flag返回0时,表明该连接已经成功建立。
  • flag返回-1时,表明该连接发生了错误,即没有成功建立连接。
    • 并会将发生的错误记录在一个全局变量errno中,其中errno的取值有:
      • errno:

注:inet_pton和socket都有可能调用失败,从而需要对其返回值进行相应的错误处理

非阻塞下connect的返回值和参数设置

对于非阻塞的connect的连接,其不会在调用connect的时候进行阻塞,而是立即返回。如果返回0,说明调用connect的时候还没来得及让connect返回便已经建立了连接;而如果返回-1,errno会记录一个错误码,如果该错误码为EINPROGRESS。则说明该连接还正在建立,并不能说明该连接出错。一个非阻塞connect的简单测试。

	int flag;
	int fd = socket(AF_INET,SOCK_STREAM,0);
	flag = fcntl(connect_fd,F_GETFL,0);		//获取文件描述符的属性
	fcntl(connect_fd, F_SETFL, flag|O_NONBLOCK);		//将文件描述符的属性设置为非阻塞
	struct sockaddr_in addr={0};
	addr.sin_family= AF_INET;
	addr.sin_port = htons(80);
	inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
	for(;;){
		flag = connect(fd,&addr,len);		//fd被设置成了非阻塞的文件描述符
		if(flag == 0){
		printf("connect  success!\n");
		break;
		}else{
			if(errno != EINPROGRESS){
				printf("connect error!"
						 "errno:%d\n",errno);
				break;
			}else{
				printf("connection is being established\n")
				sleep(1);
				continue;
			}
		}
	}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

通常如果connect函数可以最终被调用成功会打印"connection is being established"和"connect success!"。
注意:fcntl函数对文件描述符进行设置和获取的时候需要对其返回值做校验

                                </div>

另外一篇文章解析,请点击!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值