Socket 函数说明1.1 库函数综述1.1.1 套接字函数表 1.1 Windows Sockets 1.1 版本Berkeley Sockets函数函数名说明accept()确认外来连接,并将它与一个立即建立的数据套接字联系起来。
原始套接字返回到监听状态bind() 给未命名套接字赋一个本地名closesocket()从进程对象参考表中删去一个套接字,只有当SO_LINGER设置时才阻塞connect()在指定套接字上初始化连接getpeername() 获取与指定套接字连接的对等方的名字getsockname() 获取指定套接字的当前名字getsockopt() 获取与指定套接字相关的选项htonl() 将一个32位数从主机字节顺序转换为网络字节顺序htons() 将一个16 位数从主机字节顺序转换为网络字节顺序inet_addr() 将一个用网际标准点分表示法表示的字符串地址转换成网际地址值inet_ntoa() 将一个网际地址值转换成一个用点分十进制表示法表示的字符串地址ioctlsocket() 为套接字提供控制listen() 在指定套接字上监听外来连接ntohl() 将一个32位数从网络字节顺序转换为主机字节顺序ntohs() 将一个16 位数从网络字节顺序转换为主机字节顺序recv()从一个连接的套接字上接收数据recvfrom()从一个连接或未连接的套接字上接收数据select()执行多路同步I/Osend()给一个连接套接字发送数据sendto()给一个连接或未连接套接字发送数据setsockopt() 设置与指定套接字相关的选项shutdown() 关闭全双工连接的一部分socket() 建立一个通讯用的末端点,返回一个套接字注:标红函数作用在阻塞套接字上可以阻塞。
这些函数根据功能的不同可以分为如下几类:(1) 套接字函数。
此类函数包括socket(),bind(),getpeername(),getsockname()和closesocket(),它们主要完成创建,关闭套接字功能,以及对套接字命名与名字获取。
(2) 网络连接函数。
此类函数包括listen() ,accept(),connect()和shutdown(),它们完成网络连接(如虚电路)的建立与关闭。
此类函数中有部分可阻塞。
(3) 数据传输函数。
此类函数包括send(),recv() ,sendto()和recvfrom() ,它们完成网络数据的发送与接收,全部是可以阻塞的函数。
(4) 字节定序函数。
此类函数包括htonl(),htons(),ntohl()和ntohs(),它们完成主机/网络之间数据字节顺序的转换。
(5) 地址转换函数。
此类函数包括inet_addr(),inet_ntoa(),它们完成网络字符串地址和Internet 地址之间的转换。
(6) 套接字控制函数。
此类函数包括getsockopt(),setsockopt(),ioctlsocket()和select(),它们设置/获取套接字的选项,控制/检测套接字的工作状态。
其中select()函数在必要时可能阻塞。
只使用了上述函数Berkeley Sockets 源程序基本上可以不加修改地移植到Windows Sockets 环境中来。
但是,移植过来的程序有一个最大的问题是“阻塞”。
在Berkeley Sockets 中,套接字默认的工作模式是操作处于阻塞方式,一个阻塞操作可能阻塞整个Windows 环境。
在非抢先Windows环境,强烈推荐程序员使用非阻塞(异步)操作,也就是说,推荐使用Windows Sockets 提供的异步选择函数代替可能阻塞的select()函数,并且用网络事件消息来驱动可能阻塞的网络连接函数(accept()和connect())和数据传输函数,这样设计的程序能更好地工作。
1.1.2 数据库函数Windows Sockets定义了如表1.2 所示的“数据库”函数:表 1.2 Windows Sockets 1.1 版本定义的“数据库”函数函数名说明gethostbyaddr() 通过网络地址获取主机名字和地址等信息gethostbyname() 通过主机名字获取主机名字和地址等信息gethostname()获取本地主机名getprotobyname() 通过协议名获取协议名和协议号等信息getprotobynumber() 通过协议号获取协议名和协议号等信息getservbyname() 通过服务名获取服务的名字和端口等信息getservbyport() 通过端口获取服务的名字和端口等信息注:标红函数在某些条件下可以阻塞。
提供这类函数是为了获取网络特定的信息,在最初的Berkeley版本中,它们是作为在文本数据库文件中寻找信息的机构。
在Windows Sockets实现中,可能使用了不依赖于本地数据库文件的方法(如域名服务),但是对应用程序来说请求这些信息的格式是一致的,并且对应用程序来说是透明的。
调用这些函数所获得的信息存放在由Windows Sockets实现分配的一个结构中,函数返回此结构的地址。
因此,应用程序可以通过此结构指针获取所需要的信息,但它决不能试图修改此结构,更不能释放结构的任一部分。
另外,对一个线程来说,Windows Sockets实现只分配了结构的一个备份,任何Windows Sockets API 调用都可能修改此结构。
也就是说,结构指针指向的数据只在此线程的下一次Windows Sockets API 调用之前才是正确的,应用程序应该在发布任何其它Windows Sockets API 调用之前将任何需要的信息拷贝出来。
数据库函数除gethostname()之外都是阻塞的,Windows Sockets提供它们是为了Berkeley Sockets网络程序的可移植性。
在设计实现Windows Sockets 应用程序时,推荐使用Windows Sockets 提供的数据库函数的异步版本。
1.2 标准Socket 函数1.2.1 accept()语法:SOCKET WSAAPIaccept ( IN SOCKET s,OUT struct sockaddr FAR* addr,OUT int FAR* addrlen );此函数用于从套接字上接收一个连接。
它提取挂在套接字s 上的连接队列中的第一个连接,创建一个和s 有相同属性(包括使用函数WSAAsyncSelect()或WSAEventSelect()注册的异步事件,但不包括监听套接字的套接字组ID)的新数据套接字,并返回一个指向新套接字的句柄。
如果连接队列上没有等待的连接,并且套接字没有标志为非阻塞,那么accept() 阻塞调用直到出现一个连接。
如果套接字标志为非阻塞,并且队列上没有等待的连接,那么accept()返回错误WSAEWOULDBLOCK。
新创建的数据套接字不能用来接收更多的连接,它只能用于数据传输;原来的套接字仍然打开,处于监听连接状态。
参数描述:s,这是一个套接字描述符,该套接字在用作accept()函数的参数前必须先调用过listen()函数,此时它正处于监听连接的状态。
addr ,一个可选的指向缓冲区的指针,用来接收连接实体的地址,在通讯层使用。
addr的确切格式由套接字创建时建立的地址族决定。
addrlen ,一个可选的指向整数的指针,它调用时含有地址addr指向的空间的大小,返回时含有返回的地址的确切长度(字节数)。
返回值:如果没有错误发生,accept()返回一个SOCKET类型的值,表示接收到的套接字的描述符。
否则返回值INVALID_SOCKET,错误码可通过调用WSAGetLastError()函数得到。
错误码:WSANOTINITIALISED :未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。
WSAENETDOWN: Windows Sockets 实现检测到网络系统已经失败。
WSAEFAULT: 参数addrlen 太小(小于结构sockaddr 的大小),或参数addr不是用户地址空间的合法部分。
WSAEINTR:此(阻塞)调用已被WSACancelBlockingCall()函数取消。
WSAEINPROGRESS:一个阻塞的Windows Sockets 操作正在进行。
WSAEINVAL:在accept()调用之前没有执行过listen()。
WSAEMFILE:accept()队列入口空,但没有文件描述符可用(即打开的文件描述符过多)。
WSAENOBUFS:无缓冲区空间可用。
WSAENOTSOCK:描述符s不是套接字描述符。
WSAEOPNOTSUPP:s 指向的套接字不是一种支持面向连接服务类型的套接字。
WSAEWOULDBLOCK:套接字标志为非阻塞,但现在没有接收到连接。
注释:该调用只能和基于连接的套接字类型如SOCK_STREAM 一起使用。
如果参数addr 和/或addrlen 等于NULL,那么没有关于接收套接字的远程地址信息返回。
参见:bind(), connect(), listen(), select(), socket(), WSAAsyncSelect(), WSAAccept()。
1.2.2 bind()语法:int WSAAPIbind ( IN SOCKET s,IN const struct sockaddr FAR* name,IN int namelen );此函数用于未连接的数据报或流套接字,它将一本地地址与套接字连接,即建立半相关。
当一套接字用socket()创建后,它存在于一名字空间(地址族), 但它没有赋予名字。
bind()通过将一本地名字赋予一未命名的套接字, 建立起套接字的本地连接(主机地址/端口号)。
参数描述:s,指示未连接的数据报或流套接字的描述符。
name,赋给套接字的本地地址(名字)。
结构sockaddr 定义如下:struct sockaddr { u_short sa_family;char sa_data[14];}; //除sa_family 外,其它内容都以网络字节顺序表示。
namelen,地址缓冲区长度。
返回值:如果没有错误发生,bind()返回0。
否则返回值SOCKET_ERROR,错误码可通过调用WSAGetLastError()函数得到。
错误码:WSANOTINITIALISED:未初始化Windows Sockets DLL,在使用此函数之前必须有一次成功的WSAStartup()函数调用。
WSAENETDOWN :Windows Sockets 实现检测到网络系统已经失败。