3.7.5 面向连接的基本套接字函数
本小节将逐一介绍面向连接的套接字函数。
1.socket
函数定义:int socket(int af,int type,int protocol)。
函数用途:客户机/服务器使用,创建套接字。
参数说明
·af:输入参数,指定协议族,一般都为AF_INET,对应于Internet协议族。
·type:输入参数,指定套接字类型,若取值为SOCK_STREAM,表示要创建面向连接的流式套接字;若取值为SOCK_DRRAM,表示要创建面向无连接的数据报套接字;若取值为SOCK_RAW,表示要创建原始套接字。
·protocol:输入参数,指定套接字所使用的传输层协议。在Internet通信域中,此参数一般取值为0,系统会根据套接字的类型决定应使用的传输层协议。
·返回值:如果套接字创建成功,就返回一个int型的整数,它就是所创建的套接字的描述符,后续对套接字的操作,如读写数据,关闭套接字,都需要通过这个描述符来完成。这就像是在建立一个文件后,得到文件句柄一样,对文件的操作都是对文件句柄来进行的。如果套接字创建失败,就返回—1。
【例3-1】使用socket函数示例。
int sockfd=socket(AF_INET,SOCK_STREAM,0);
例子中sockfd就是创建套接字的描述符,如果创建成功,则是一个大于0的整型数;如果创建失败,则为—1。
2.bind
函数定义:int bind(int sockfd,struct sockaddr*my_addr,int addrlen)。
函数用途:服务器端使用,将套接字与指定的本机IP地址和端口绑定。端口一般是保留端口,当然也可以是由通信双方事先约定好的自由端口。服务器端可能会有多块网卡,在指定IP地址时,可以使用INADDR_ANY参数来指定多块网卡。
参数说明
·sockfd:输入参数,套接字描述符,该描述符由socket()函数创建,要将它绑定到指定的网络地址上。
·my_addr:输入参数,是一个指向sockaddr结构变量的指针,所指向的结构中保存着特定的网络地址,即要和套接字绑定的本地网络地址。在Internet通信域中,此网络地址由IP地址+传输层端口号构成。
·参数addrlen:输入参数,sockaddr结构的长度一般可以使用sizeof(struct sockaddr)来填写。
·返回值:如果返回0,表示已经正确地实现了绑定;如果返回—1,表示有错。
【例3-2】使用bind函数示例。
例子说明
①在填写网络地址变量my_addr时,IP地址部分填写的是inet_addr(INADDR_ANY),其含义是如果本机有多块网卡(多宿主机),则将多块网卡上的多个IP地址都填写进去。当然这里也允许只填写其中某个IP地址,但是这样就会造成执行完绑定操作后,服务器只能接收客户机发往这个IP地址的连接请求,而不能接收发往服务器中其他网卡上的IP地址的连接请求。
②在调用bind函数时,第2个输入参数是(sockaddr*)my_addr。为什么要这样写呢?原来bind函数的定义中第2个参数是通用网络地址结构sockaddr,为了套接字可以被各种网络协议栈所使用,而不仅仅是为Internet协议族使用。在本例中,使用的是Internet协议族,因此变量my_addr使用的是一个INET协议族的网络地址结构sockaddr_in,但是在调用bind函数时,需要将此INET协议族的网络地址结构强制转换为通用网络地址结构。
3.listen
函数定义:int listen(int sockfd,int queuesize)。
函数用途:服务器端程序使用,这个函数告诉套接字开始监听客户机的连接请求,并且参数queuesize规定了等待连接请求队列的最大长度。操作系统为每个监听套接字各自建立了一个用来等待连接的缓冲区队列。队列最初是空的,是一个先进先出的缓冲区队列。如果缓冲区有空闲位置,则接收一个来自客户端的连接请求,并将其放入队列尾;如果缓冲区队列满了,则拒绝客户机端的连接请求。
参数说明
·sockfd:输入参数,套接字描述符,通过它来监听来自客户机端的连接请求。
·queuesize:输入参数,等待连接队列的最大长度,由编程人员指定。
·返回值:函数正确执行返回0,出错返回—1。
【例3-3】使用listen函数示例。
int n=l isten(sockfd,10); //最大同时接收10个连接
4.accept
函数定义:int accept(int sockfd,struct sockaddr*addr,int*addrlen)。
函数用途:服务器端程序使用,从等待连接请求队列中取出第1个连接请求并接收,为这个连接请求创建一个响应套接字,后续与此连接请求对应的客户端通信时将通过这个响应套接字进行。此调用仅适用于面向连接的套接字,与listen函数配套使用。它的第2个参数和第3个参数是输出参数,能通过这两个参数得到客户机端的网络地址信息。
参数说明
·sockfd:输入参数,监听套接字描述符。
·addr:输出参数,带回指向连接套接字客户机端网络地址信息的数据结构的指针。当不关心客户机端地址信息时,可以将此参数置为NULL。
·addrlen:输入输出参数。调用accept函数前,应先将此参数值初始设置为addr结构的长度,不能为0或者NULL,调用完毕后返回所接收的客户机端的网络地址的精确长度。
·返回值:如果调用成功,返回一个新的响应套接字描述符,后续与此连接请求对应的客户端通信时将通过这个响应套接字进行;如果出错返回—1。
【例3-4】使用accept函数示例。
5.connect
函数定义:int connect(int sockfd,struct sockaddr*remoteaddr,int addrlen)。
函数用途:客户机端使用,用来请求连接到服务器端的套接字。调用此函数会启动与指定服务器的传输层建立连接,将连接请求发送到服务器端,服务器根据等待连接请求队列的情况决定是否接收此请求到等待缓冲区。
参数说明
·sockfd:输入参数,客户机端进程生成的套接字描述符,客户机端要通过这个套接字向服务器端发送连接请求,要用它来与服务器端建立连接,并与服务器端交换数据,可以将这个套接字称为请求套接字。如果connect函数执行成功,则此套接字处于已绑定和已连接的状态。
·remoteaddr:输入参数,指向sockaddr通用地址结构的指针,该结构中存放了要连接的服务器端的网络地址。这个参数使用的是通用地址结构而不是INET地址结构。
·addrlen:输入参数,sockaddr结构的长度。
【例3-5】使用connect函数示例。
6.send和recv
函数定义
·int send(int sockfd,char*buffer,int len,int flags)。
·int recv(int sockfd,char*buffer,int len,int flags)。
函数用途:客户机/服务器端使用,发送、接收数据。
参数说明
·sockfd:输入参数,对于服务器端来说是响应套接字描述符(注意不是监听套接字),对于客户机端来说是请求套接字描述符。
·buffer:输出参数,用来发送/接收的缓冲区指针。
·len:输入参数,对于send函数是要发送的字节数,对于recv函数是接收缓冲区的大小。
·flags:输入参数,调用方式,一般置为0。
·返回值:对于send函数,返回实际发送出去的字节数;对于recv函数,返回接收到的字节数。
【例3-6】使用send和recv函数示例。
7.close
函数定义:int close(int sockfd)。
函数用途:关闭套接字。
参数说明
·sockfd:输入参数,套接字描述符。
·返回值:如果成功则返回0,失败返回—1。
【例3-7】使用close函数示例。
close(sockfd);