有关套接口操作函数(经常忘掉里头一些细节,留着查看)

13.2.2  socket函数

socket函数的具体信息如表13.1所示。

表13.1                                                           socket函数

头文件

<sys/types.h>

<sys/socket.h>

函数形式

int socket(int domain, int type, int protocol);

返回值

成功

失败

是否设置errno

创建的socket的文件描述符

−1

说明:

socket函数用于创建通信的套接字,并返回该套接字的文件描述符。参数domain指定了通信域,该参数用于选择通信协议族,其取值情况如表13.2所示。

表13.2                                                    domain取值情况表

名    称

含    义

备    注

PF_UNIX, PF_LOCAL

本地通信

“man 7 UNIX”可以获得具体帮助信息

PF_INET

IPv4协议

“man 6 ip”可以获得具体帮助信息

PF_INET6

IPv6协议

PF_IPX

Novell公司的IPX协议

PF_NETLINK

与内核间的接口

“man 7 netlink”可以获得具体帮助信息

PF_X25

ITU-T X.25 / ISO-8208

“man 7 x25”可以获得具体帮助信息

PF_AX25

无线AX.25协议

PF_ATMPVC

访问原始ATM的PVC

PF_APPLETALK

苹果公司的Appletalk协议

“man 7 ddp”可以获得具体帮助信息

PF_PACKET

底层包接口

“man 7 packet”获得具体帮助信息

参数type用于指定套接字的类型。套接字类型除了前面提到的流套接字、数据报套接字及原始套接字外,还有其他的几种类型,如表13.3所示。

表13.3                                                   type参数可取值情况

套接字类型

说    明

SOCK_STREAM

提供有序、可靠、双向及基于连接的字节流。支持带外传输机制

SOCK_DGRAM

支持数据报

SOCK_SEQPACKET

提供有序、可靠、双向基于连接的数据报通信

SOCK_RAW

提供对原始网络协议的访问

SOCK_RDM

提供可靠的数据报层,但是不保证有序性

SOCK_PACKET

该参数已经废除

流套接字(SOCK_STREAM)与管道类似,是一种全双工的比特流。流套接字在发送或接收数据前必须处于连接状态。实现流套接字的通信协议保证了传输的数据不会丢失。

参数protocol用于指定套接字使用的通信协议。正常情况下,对于给定的协议族,只有单一的协议支持特定的套接字类型。这时,只要将protocol参数设置为0即可。

错误信息:

EACCES:创建指定类型的套接字失败。

EAFNOSUPPORT:不支持指定的地址族。

EINVAL:未知协议或未知的协议族。

EMFILE:进程文件表溢出。

ENFILE:达到打开文件的系统限制。

ENOBUFS或ENOMEM:内存不足。

EPROTONOSUPPORT:指定的协议类型在该域中不支持。

13.2.3  bind函数

bind函数用于将套接字与指定端口相连,其具体信息如表13.4所示。

表13.4                                                             bind函数

头文件

<sys/types.h>

<sys/socket.h>

函数形式

int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);

返回值

成功

失败

是否设置errno

0

−1

说明:

当调用socket函数创建套接字后,该套接字并没有与本机地址和端口等信息相连,bind函数将完成这些工作。bind函数中的sockfd参数为调用socket函数后返回的文件描述符。my_addr参数为指向sockaddr结构体的指针(该结构体中保存有端口和IP地址信息)。addlen参数为结构体sockaddr的长度。

错误信息:

EACCES:地址受到保护,用户非超级用户。

EADDRINUSE:指定的地址已经在使用。

EBADF:sockfd参数为非法的文件描述符。

EINVAL:socket已经和地址绑定。

ENOTSOCK:参数sockfd为文件描述符。

实例演练:

下面的代码来自于Linux系统的man帮助,注意创建套接字和使用bind函数实现socket的文件描述符与地址信息绑定的过程。

#include <sys/socket.h>

#include <sys/un.h>

#include <stdlib.h>

#include <stdlio.h>

#define MY_SOCK_PATH "/somepath"

int

main(int argc, char *argv[])

{

     int sfd;

     struct sockaddr_un addr;

   //创建通信的套接字

     sfd = socket(AF_UNIX, SOCK_STREAM, 0);

     if (sfd == -1) {

         perror("socket");

         exit(EXIT_FAILURE);

     }

   //初始化addr变量

     memset(&addr, 0, sizeof(struct sockaddr_un));

     addr.sun_family = AF_UNIX;

     strncpy(addr.sun_path, MY_SOCK_PATH,

            sizeof(addr.sun_path) - 1);

   //将端口信息与套接字绑定

     if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) {

            perror("bind");

            exit(EXIT_FAILURE);

      }

     …

}

13.2.4  listen函数

服务器必须等待客户的连接请求,listen函数用于实现等待功能,该函数的具体信息如表13.5所示。

表13.5                                                            listen函数

头文件

<sys/socket.h>

函数形式

int listen(int sockfd, int backlog);

返回值

成功

失败

是否设置errno

0

−1

说明:

listen函数中,参数sockfd为调用socket函数获得的套接字的文件描述符信息。backlog参数为提出连接请求后,在服务器接收该连接请求时的等待队列中的连接数。默认情况,该值为20。

系统调用listen只用于套接字类型为SOCK_STREAM或SOCK_SEQPACKET的场合。

错误信息:

EADDRINUSE:另一个socket也在监听同一个端口。

EBADF:参数sockfd为非法的文件描述符。

ENOTSOCK:参数sockfd不是文件描述符。

EOPNOTSUPP:套接字类型不支持listen操作。

13.2.5  accept函数

处于监听状态的服务器在获得客户机的连接请求后,会将其放置在等待队列中。当系统空闲时,将接受客户机的连接请求。接收客户机的连接请求使用accept函数,该函数的具体信息如表13.6所示。

表13.6                                                           accept函数

头文件

<sys/types.h>

<sys/socket.h>

函数形式

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

返回值

成功

失败

是否设置errno

返回新的套接字文件描述符

−1

说明:

accept函数用于面向连接类型的套接字类型(SOCK_STREAM和SOCK_SEQPACKET)。accept函数将从连接请求队列中获得连接信息,创建新的套接字,并返回该套接字的文件描述符。新创建的套接字用于服务器与客户机的通信,而原来的套接字仍然处于监听状态。

accept函数的sockfd参数为监听的套接字描述符。addr参数为指向结构体sockaddr的指针。参数addrlen为addr参数指向的内存空间的长度。

错误信息:

EAGAIN:套接字处于非阻塞状态,当前没有连接请求。

EBADF:非法的文件描述符。

ECONNABORTED:连接中断。

EINTR:系统调用被信号中断。

EINVAL:套接字没有处于监听状态,或非法的addrlen参数。

EMFILE:达到进程打开文件描述符限制。

ENFILE:达到打开文件数限制。

ENOTSOCK:文件描述符为文件的文件描述符。

EOPNOTSUPP:套接字类型不是SOCK_STREAM。

13.2.6  connect函数

对于客户机而言,要与服务器进行通信,需要向服务器发出连接请求。connect函数用于完成这项功能,该函数的具体信息如表13.7所示。

表13.7                                                         connect函数

头文件

<sys/types.h>

<sys/socket.h>

函数形式

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

返回值

成功

失败

是否设置errno

0

−1

说明:

connect函数将使用参数sockfd中的套接字连接到参数serv_addr中指定的服务器。参数addrlen为serv_addr指向的内存空间大小。

如果参数sockfd的类型为SOCK_DGRAM,serv_addr参数为数据报发往的地址,且将只接收该地址的数据报。如果sockfd的类型为SOCK_STREAM或SOCK_SEQPACKET,调用该函数将连接serv_addr中的服务器地址。

错误信息:

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

EADDRINUSE:本地地址处于使用状态。

EAFNOSUPPORT:参数serv_add中的地址非合法地址。

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

EALREADY:套接字为非阻塞套接字,并且原来的连接请求还未完成。

EBADF:非法的文件描述符。

ECONNREFUSED:远程地址并没有处于监听状态。

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

EINPROGRESS:套接字为非阻塞套接字,且连接请求没有立即完成。

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

EISCONN:已经连接到该套接字。

ENETUNREACH:网络不可到达。

ENOTSOCK:文件描述符不与套接字相关。

ETIMEDOUT:连接超时。

13.2.7  发送与接收数据

当服务器与客户机之间成功建立连接后,可以调用read和write函数来实现对套接字的读写,以实现网络中不同主机间的通信。Linux系统还提供了send和recv函数,用于实现与read和write函数相同的功能。而且send和recv的功能要比read函数和write函数更为全面。send函数的具体信息如表13.8所示。

表13.8                                                            send函数

头文件

<sys/types.h>

<sys/socket.h>

函数形式

ssize_t send(int s, const void *buf, size_t len, int flags);

返回值

成功

失败

是否设置errno

返回实际发送的数据的字节数

−1

说明:

send函数用于将信息发送到指定的套接字文件描述符中。该函数只能用于已经建立连接的socket通信中,即只用于面向连接的通信中。参数s为要发送数据的套接字文件描述符。buf参数为指向要发送数据的指针。len为要发送数据的长度。flag参数可以包含如下的参数。

l     MSG_CONFIRM(Linux 2.3以上的内核版本支持):通知数据链路层发生了转发,且得到了通信另一段的回应。如果链路层没有得到回应,将使用ARP或其他协议来探测网络上的主机。该参数只用于SOCK_DGRAM和SOCK_RAW类型的套接字。

l     MSG_DONTROUTE:不通过网关发送数据,只将数据发送到同一子网中的计算机。该参数通常用于诊断或路由程序中,只用于路由的协议族中,包套接字不能使用该参数。

l     MSG_DONTWAIT:使用非阻塞操作。如果操作将阻塞,并返回EAGAIN错误。

l     MSG_EOR:结束记录(当套接字类型是SOCK_SEQPACKET时使用)。

l     MSG_MORE(Linux 2.4.4以上内核版本支持):调用者有更多的数据要发送。

l     MSG_OOB:通过套接字发送带外数据(套接字需要支持这一行为,例如,使用SOCK_STREAM类型的套接字)。

write函数与send函数在flag为0时的功能相同。

错误信息:

下面列出send函数常见的错误信息。

EBADF:非法的文件描述。

ECONNRESET:连接重置。

EDESTADDRREQ:在套接字操作中没有指定目标地址。

EFAULT:参数指向了非法的地址空间。

EINTR:数据发送前,捕获到信号。

EINVAL:非法参数。

ENOTSOCK:参数非套接字的文件描述符。

ENOMEM:内存不足。

recv函数可以实现从指定套接字中读取发送来的消息,该函数的具体信息如表13.9所示。

表13.9                                                             recv函数

头文件

<sys/types.h>

<sys/socket.h>

函数形式

ssize_t recv(int s, void *buf, size_t len, int flags);

返回值

成功

失败

是否设置errno

0

−1

说明:

recv函数用于从指定套接字中获取发送的消息。与send函数一样,该函数只能用于已经建立连接的socket通信中,即只用于面向连接的通信中。参数s为要读取信息的套接字文件描述符。buf参数为指向要保存数据缓冲区的指针。而len为该缓存的最大长度。

参数flags可以包含如下的标志。

l     MSG_DONTWAIT:使用非阻塞操作。如果操作将阻塞,将返回EAGAIN错误。

l     MSG_OOB:通过套接字发送带外数据(套接字需要支持这一行为,例如使用SOCK_STREAM类型的套接字)。

l     MSG_PEEK:该标志表示从接收队列的开始处查看数据,而不从缓冲区中删除数据。

l     MSG_TRUNC:返回包的真实长度,即使该长度超出了传递的缓存长度。该标志只用于流套接字。

l     MSG_WAITALL:该标志将使得操作处于阻塞状态,直到获得全部数据

当flags参数为0时,recv函数等同与read函数的功能。

错误信息:

EAGAIN:在接收到数据前,接收操作处于阻塞或直至超时。

EBADF:非法的文件描述符。

ECONNABORTED:远程主机拒绝网络连接。

EFAULT:指向接收数据的缓冲区指针指向了非法地址空间。

EINTR:系统调用被信号中断。

EINVAL:非法参数。

ENOTCONN:套接字使用了面向连接的协议,但是并没有建立连接。

ENOTSOCK:文件描述符为文件的文件描述符。

13.2.8  关闭套接字

在完成通信后,可以使用close函数或shutdown函数来关闭套接字。close函数的调用形式为:

close(sockfd);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值