socket网络通信中的 listen(),connecet() 和 accept()函数

一、listen() 函数

1.作用:

  listen() 函数把主动连接套接字变为被动连接的套接字,使得这个 socket 可以接受其他 socket 的连接请求,从而成为一个服务端的 socket。
在这里插入图片描述

2.函数声明及参数

2.1 函数声明

int listen(int sockfd, int backlog);

2.2 函数参数

  (1)参数 sockfd:

  参数sockfd是已经被bind过的socket(这个函数是监听,肯定是先绑定了,才监听)。

  socket函数返回的socket是一个主动连接的socket,在服务端的编程中,程序员希望这个socket可以接受外来的连接请求,也就是被动等待客户端来连接。由于系统默认时认为一个socket是主动连接的,所以需要通过某种方式来告诉系统,程序员通过调用listen函数来完成这件事。

  (2)参数backlog,这个参数涉及到一些网络的细节,比较麻烦,填5、10都行,一般不超过30。

  (3) 当调用listen之后,服务端的socket就可以调用accept来接受客户端的连接请求。

返回值:成功则返回0,失败返回-1,错误原因存于errno 中。

listen函数一般不会返回错误。

3.注意事项

  当服务端程序还没有开始监听时,客户端请求连接时,会出现无法连接。

  测试:
(1)在 listen() 函数前加上 sleep() 让 listen() 函数沉睡一会儿
在这里插入图片描述
(2)客户端请求连接

在这里插入图片描述

二、accept() 函数

1.作用:

  之前说 accept() 函数是接受客户端的连接,准确的说法应该是:从准备好的请求连接队列中取出(获取)一个请求,如果队列为空,accept函数将阻塞等待。

在这里插入图片描述

  测试:
  (1)把 socket 设为监听模式后,让程序沉睡一会儿
在这里插入图片描述
  (2)如果这个时候客户端请求连接,但是这个连接请求是还没有进到连接队列的,因为我用sleep函数让服务端程序沉睡一会。这个时候队列是空的,要过了sleep规定的时间,连接请求才能进去队列。accept函数才能从中获取连接请求。

在这里插入图片描述

客户端请求连接
在这里插入图片描述
等待了一段时间,才能从中获取请求连接。
在这里插入图片描述

2.函数声明及参数

2.1 函数声明:

  根据作用也可以猜测一下这个函数的参数了,客户端请求连接的话,怎么标识客户端?IP地址,所以参数中要有一个参数是用来存放客户端的地址信息的。

  socket 通信就是服务端和客户端的两个 socket 进行通信,因为参数中有了一个参数是客户端的地址信息了,那么有一个参数应该是服务端的 socket

  accept函数,是从准备好的连接请求队列里面取出一个客户端的请求,并把这个客户端的地址信息放到参数的 sockaddr_in 结构体里面。

int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

2.2 函数参数

  参数sockfd:
是已经被listen过的socket。

  参数addr:
用于存放客户端的地址信息,用sockaddr结构体表达,如果不需要客户端的地址,可以填0。

参数addrlen用于存放addr参数的长度,如果addr为0,addrlen也填0。

accept函数等待客户端的连接,如果没有客户端连上来,它就一直等待,这种方式称之为阻塞。

accept等待到客户端的连接后,创建一个新的socket,函数返回值就是这个新的socket,服务端使用这个新的socket和客户端进行报文的收发。

返回值:
  成功则返回0,失败返回-1,错误原因存于errno 中。

accept在等待的过程中,如果被中断或其它的原因,函数返回-1,表示失败,如果失败,可以重新accept。

2.3 注意

  int  clientfd;                  // 客户端的socket。
  int  socklen=sizeof(struct sockaddr_in); // struct sockaddr_in的大小
  struct sockaddr_in clientaddr;  // 客户端的地址信息。
  clientfd=accept(listenfd,(struct sockaddr *)&clientaddr,(socklen_t*)&socklen);

  看这段代码,为什么还要定义一个 clientfd socket 呢?直接用 listenfd socket 来通信(发送接收报文)不行吗?

  重新定义一个用于通信的 socket 的主要原因是 :有时候连接服务端的客户端不止一个,如果只用 listenfd socket 通信是不行的,多于一个客户端就分不清是谁发过来的数据了。
在这里插入图片描述
在这里插入图片描述

  所以这段代码通常是和循坏一起使用的,创建多个通信的socket

 clientfd=accept(listenfd,(struct sockaddr *)&clientaddr,(socklen_t*)&socklen);

三、connect() 函数

1.作用

  客户端向服务器发起连接请求。

2.函数声明及参数

  根据函数的作用,我们可以猜出,函数的参数有哪些。这个函数是客户端用来连接服务端的,所以要有服务端的地址信息(sockaddr),还有客户端的信息(客户端的信息放在socket里面)

在这里插入图片描述

int connect (int sockfd, struct sockaddr * serv_addr, int addrlen);

  (1)函数说明:

  connect 函数用于将参数 sockfd 的socket 连接至参数 serv_addr 指定的服务器(就是将客户端的socket连接到服务器)。参数 addrlen 为 sockaddr 的结构长度。

  (2)返回值:
  成功则返回0,失败返回-1,错误原因存于 errno 中。

  (3)connect 函数只用于客户端,因为是客户端去连接。如果服务端的地址错了,或端口号错了,或服务端没有启动,connect 一定会失败。

四、总结

  1.服务端在调用 listen() 之前,客户端不能向服务端发起连接请求。(这个就像是银行里的前台还没开始上班,就不要去请求别人的帮助)

  2.服务端调用 listen() 函数后,服务端的socket开始监听客户端的连接。(到了上班的时间,前台开始工作,等待用户)

  3.客户端调用 connect() 函数向服务端发起连接请求。

  4.在TCP底层,客户端和服务端握手后建立起通信通道,如果有多个客户端请求,在服务端就会形成一个已准备好的连接的队列。
在这里插入图片描述

  5.服务端调用 accept() 函数从队列中获取一个已准备好的连接,函数返回一个新的 socket ,新的 socket 用于与客户端通信,listen 的 socket 只负责监听客户端的连接请求。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
accept函数是在socket编程用于接受客户端连接的函数。当服务器端创建了一个监听socket后,可以调用accept函数来等待客户端的连接请求。 accept函数的原型为: ```c int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ``` 其,sockfd是服务器端创建的监听socket的文件描述符;addr是指向struct sockaddr类型的指针,用于存储客户端的IP地址和端口号;addrlen是一个指向socklen_t类型的指针,用于存储客户端地址结构体的长度。 accept函数的工作流程如下: 1. 服务器调用listen函数socket设置为监听状态,等待客户端连接。 2. 当有客户端发起连接请求时,服务器调用accept函数进行处理。 3. accept函数会阻塞等待,直到有客户端连接请求到达。 4. 当有连接请求到达时,accept函数会创建一个新的socket,并返回该新socket的文件描述符。 5. 这个新的socket会与客户端建立连接,服务器端可以通过该socket与客户端进行通信。 6. 同时,accept函数会将客户端的IP地址和端口号存储在addr参数所指向的结构体,并将结构体的长度存储在addrlen参数。 需要注意的是,accept函数在没有新的连接请求到达时会一直阻塞等待,直到有新的连接请求才会返回。如果需要非阻塞地等待连接请求,可以通过设置socket为非阻塞模式或者使用select函数来实现。另外,accept函数一般会在一个循环使用,以便持续接受客户端的连接请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值