Unix 网络编程函数返回值

本文详细介绍了网络编程的基础概念,包括套接字的创建、绑定、连接、监听、数据传输及关闭等核心过程。深入解析了socket(), bind(), connect(), accept(), listen(), send(), recv(), select()和closesocket()等关键函数的使用方法与返回值分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建套接字──socket()

SOCKET PASCAL FAR socket(int af, int type, int protocol);

该调用要接收三个参数:af、type、protocol。参数af指定通信发生的区域,:AF_UNIX、AF_INET、AF_NS等,而DOS、 WINDOWS中仅支持AF_INET,它是网际网区域。因此,地址族与协议族相同。参数type 描述要建立的套接字的类型。这里分三种:一是TCP流式套接字(SOCK_STREAM)提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。

对于windows环境下,在调用该函数之前需首先调用WSAStartup函数完成对Winsock服务的初始化,如

#include<WinSock2.h>

WSADATA wdata;

if ( WSAStartup(MAKEWORD(2,2), &wdata) !=0 ){

return INVALID_SOCKET;

}

后面即可调用socket函数,参数意义与linux环境一致。

返回值剖析:
0 – 成功,-1 - 出错

errno获得:

EACCES没有权限建立制定的domain的type的socket
EAFNOSUPPORT不支持所给的地址类型
EINVAL不支持此协议或者协议不可用
EMFILE进程文件表溢出
ENFILE已经达到系统允许打开的文件数量,打开文件过多
ENOBUFS/ENOMEM内存不足。socket只有到资源足够或者有进程释放内存
EPROTONOSUPPORT制定的协议type在domain中不存在

 

指定本地地址──bind()

int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);

参数s是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。参数name 是赋给套接字s的本地地址(名字),其长度可变,结构随通信域的不同而不同。namelen表明了name的长度.如果没有错误发生,bind()返回0。否则返回SOCKET_ERROR

返回值剖析:

如无错误发生,则bind()返回0。否则的话,将返回-1,应用程序可通过WSAGetLastError()获取相应错误代码

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。

WSAENETDOWN:套接口实现检测到网络子系统失效。

WSAEADDRINUSE:所定端口已在使用中(参见setoption()中的SO_REUSEADDR选项)。

WSAEFAULT:namelen参数太小(小于sockaddr结构的大小)。

WSAEINPROGRESS:一个阻塞的套接口调用正在运行中。

WSAEAFNOSUPPORT:本协议不支持所指定的地址族。

WSAEINVAL:该套接口已与一个地址捆绑。

WSAENOBUFS:无足够可用缓冲区,连接过多。

WSAENOTSOCK:描述字不是一个套接口。

建立套接字连接──connect()

int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen);

参数s是欲建立连接的本地套接字描述符。参数name指出说明对方套接字地址结构的指针。对方套接字地址长度由namelen说明。

  如果没有错误发生,connect()返回0。否则返回值SOCKET_ERROR。在面向连接的协议中,该调用导致本地系统和外部系统之间连接实际建立。

返回值剖析:

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

 

错误代码: 
EBADF 参数sockfd 非合法socket处理代码
EFAULT 参数serv_addr指针指向无法存取的内存空间
ENOTSOCK 参数sockfd为一文件描述词,非socket。
EISCONN 参数sockfd的socket已是连线状态
ECONNREFUSED 连线要求被server端拒绝。
ETIMEDOUT 企图连线的操作超过限定时间仍未有响应。
ENETUNREACH 无法传送数据包至指定的主机。
EAFNOSUPPORT sockaddr结构的sa_family不正确。
EALREADY socket为不可阻塞且先前的连线操作还未完成。
--------------------- 
 

建立套接字连接──accept()

SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

参数s为本地套接字描述符,在用做accept()调用的参数前应该先调用过listen()。addr 指向客户方套接字地址结构的指针,用来接收连接实体的地址。addr的确切格式由套接字创建时建立的地址族决定。addrlen 为客户方套接字地址的长度(字节数)。如果没有错误发生,accept()返回一个SOCKET类型的值,表示接收到的套接字的描述符。否则返回值INVALID_SOCKET

返回值剖析:

accept函数接受一个客户端请求后会返回一个新的SOCKFD值,当有不同的客户端同时有不同请求时,会返回不同的SOCKFD的值。阻塞函数:如果没有新的连接到来,会阻塞在函数中。

Linux下,accept()把已等待的网络错误传给新建立的连接,当作是accept()返回的错误。这于其他的BSD实现是不同的。为了可靠运行,应该在accept()之后检测协议已定义的一些网络错误,并把这些错误当作EAGAIN并重试。对于TCP/IP协议来说,主要有错误:

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。

WSAENETDOWN:套接口实现检测到网络子系统失效。

WSAEFAULT:addrlen参数太小(小于socket结构的大小)。

WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。

WSAEINPROGRESS:一个阻塞的套接口调用正在运行中。

WSAEINVAL:在accept()前未激活listen()。

WSAEMFILE:调用accept()时队列为空,无可用的描述字。

WSAENOBUFS:无可用缓冲区空间。

WSAENOTSOCK:描述字不是一个套接口。

WSAEOPNOTSUPP:该套接口类型不支持面向连接服务。

WSAEWOULDBLOCK:该套接口为非阻塞方式且无连接可供接受。

WSAECONNRESET:接受连接后在accept返回之前,被远程客户端断开连接。

监听连接──listen()

int PASCAL FAR listen(SOCKET s, int backlog);

参数s标识一个本地已建立、尚未连接的套接字号,服务器愿意从它上面接收请求。backlog表示请求连接队列的最大长度,用于限制排队请求的个数,目前允许的最大值为5。如果没有错误发生,listen()返回0。否则它返回SOCKET_ERROR

返回值剖析:

无错误,返回0,

否则,返回SOCKET ERROR,windows上可以调用函数WSAGetLastError取得错误代码,在Linux可使用errno。

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。

WSAENETDOWN:套接口实现检测到网络子系统失效。

WSAEADDRINUSE:试图用listen()去监听一个正在使用中的地址。

WSAEINPROGRESS:一个阻塞的套接口调用正在运行中。

WSAEINVAL:该套接口未用bind()进行捆绑,或已被连接。

WSAEISCONN:套接口已被连接。

WSAEMFILE:无可用文件描述字。

WSAENOBUFS:无可用缓冲区空间。

WSAENOTSOCK:描述字不是一个套接口

WSAEOPNOTSUPP:该套接口不正常listen()调用。

数据传输──send()与recv()

int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags);

参数s为已连接的本地套接字描述符。buf 指向存有发送数据的缓冲区的指针,其长度由len 指定。flags 指定传输控制方式,如是否发送带外数据等。如果没有错误发生,send()返回总共发送的字节数。否则它返回SOCKET_ERROR

返回值剖析:

若无错误发生,send()返回所发送数据的总数(请注意这个数字可能小于len中所规定的大小)。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码

错误代码:

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。

WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。

WSAEACESS:要求地址为广播地址,但相关标志未能正确设置。

WSAEINTR:通过一个WSACancelBlockingCall()来取消一个(阻塞的)调用。

WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。

WSAEFAULT:buf参数不在用户地址空间中的有效位置。

WSAENETRESET:由于WINDOWS套接口实现放弃了连接,故该连接必需被复位。

WSAENOBUFS:WINDOWS套接口实现报告一个缓冲区死锁

WSAENOTCONN:套接口未被连接。

WSAENOTSOCK:描述字不是一个套接口。

WSAEOPNOTSUPP:已设置了MSG_OOB,但套接口非SOCK_STREAM类型。

WSAESHUTDOWN:套接口已被关闭。一个套接口以1或2的how参数调用shutdown()关闭后,无法再用send()函数。

WSAEWOULDBLOCK:

WSAEMSGSIZE:套接口为SOCK_DGRAM类型,且数据报大于WINDOWS套接口实现所支持的最大值。

WSAEINVAL:套接口未用bind()捆绑。

WSAECONNABORTED:由于超时或其他原因引起虚电路的中断。

WSAECONNRESET:虚电路被远端复位。

 

int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags);

  参数s 为已连接的套接字描述符。buf指向接收输入数据缓冲区的指针,其长度由len 指定。flags 指定传输控制方式,如是否接收带外数据等。如果没有错误发生,recv()返回总共接收的字节数。如果连接被关闭,返回0。否则它返回SOCKET_ERROR

返回值剖析:

返回值:

若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码

错误代码:

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。

WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。

WSAENOTCONN:套接口未连接。

WSAEINTR:阻塞进程被WSACancelBlockingCall()取消。

WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。

WSAENOTSOCK:描述字不是一个套接口。

WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM类型的。

WSAESHUTDOWN:套接口已被关闭。当一个套接口以0或2的how参数调用shutdown()关闭后,无法再用recv()接收数据。

WSAEWOULDBLOCK:套接口标识为非阻塞模式,但接收操作会产生阻塞。

WSAEMSGSIZE:数据报太大无法全部装入缓冲区,故被剪切。

WSAEINVAL:套接口未用bind()进行捆绑。

WSAECONNABORTED:由于超时或其他原因,虚电路失效。

WSAECONNRESET:远端强制中止了虚电路。

linux版本:

第四个参数:

MSG_DONTROUTE 绕过路由表查找。

MSG_DONTWAIT 仅本操作非阻塞。

MSG_OOB 发送或接收带外数据。

MSG_PEEK 窥看外来消息。

MSG_WAITALL 等待所有数据。

返回值:

若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。如果发生错误,返回-1,应用程序可通过perror()获取相应错误信息。

输入/输出多路复用──select()

select() 调用用来检测一个或多个套接字的状态。对每一个套接字来说,这个调用可以请求读、写或错误状态方面的信息。请求给定状态的套接字集合由一个fd_set结构指示。在返回时,此结构被更新,以反映那些满足特定条件的套接字的子集,同时, select()调用返回满足条件的套接字的数目,其调用格式如下:

  int PASCAL FAR select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);
参数readfds指向要做读检测的套接字描述符集合的指针,调用者希望从中读取数据。参数writefds 指向要做写检测的套接字描述符集合的指针。 exceptfds指向要检测是否出错的套接字描述符集合的指针。timeout指向select()函数等待的最大时间,如果设为NULL则为阻塞操作。select()返回包含在fd_set结构中已准备好的套接字描述符的总数目,或者是发生错误则返回SOCKET_ERROR

返回值剖析:

关闭套接字──closesocket()

BOOL PASCAL FAR closesocket(SOCKET s);

  参数s待关闭的套接字描述符。如果没有错误发生,closesocket()返回0。否则返回值SOCKET_ERROR

返回值剖析:

当返回为0时,表示超时。

当返回为正数时,表示已经准备好的描述符数。

select()返回后,在3个描述符集里,依旧是1的位就是准备好的描述符。这也就是为什么,每次用select后都要用FD_ISSET的原因。

WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。

WSAENETDOWN:套接口实现检测到网络子系统失效。

WSAEINVAL:超时时间值非法,

WSAEINTR:通过一个WSACancelBlockingCall()来取消一个阻塞的

WSAEINPROGRESS:一个阻塞的套接口调用正在运行中。

WSAENOTSOCK:描述字集合中包含有非套接口的元素。

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值