四.socket函数
Windows sockets函数socket建立一个socket。
SOCKET socket(
int af,
int type,
int protocol
);
参数
af[in] 一个地址簇。
type[in] socket的类型,有SOCK_STREAM和SOCK_DATAGRAM两种类型。
SOCK_STREAM 提供连续的、可靠的、双向的、基于连接的字节流的数据传输机制。使用TCP协议。
SOCK_DATAGRAM 支持数据报,数据报是面向非连接的、不可靠的、大小固定的数据。使用UDP协议。
protocol[in] 使用指定地址簇中的一个特别的协议。
注意
socket函数建立一个socket描述符,底层服务来分配资源和绑定socket。
返回值
若没有错误,socket函数返回一个指向新建的socket的描述符。否则,返回INVALID_SOCKET,你可以用WSAGetLastError函数获取错误码。
错误码
WSANOTINITIALISED 未初始化,请先调用WSAStartup初始化socket。
WSAENETDOWN 网络底层系统错误。
WSAEAFNOSUPPORT 地址簇不支持。
WSAEINPROGRESS 线程被阻塞,或者在回调。
WSAEMFILE socket操作符不可用。
WSAENOBUFS 没有缓冲区可用。
WSAEPROTONOSUPPORT 不支持的协议。
WSAEPROTOTYPE 协议类型错误。
WSAESOCKTNOSUPPORT 协议类型不受地址簇支持。
五.bind函数
Windows sockets函数bind关联一个本地地址到一个socket。
int bind(
SOCKET s,
const struct sockaddr FAR* name,
int namelen
);
参数
s[in] 指明一个未绑定的socket的描述器。
name[in] 将sockaddr指定的地址赋值给socket。
namelen[in] 名称的长度。
注意
bind函数应用在调用connect或者listen函数之前的未连接的socket上。它用于绑定面向连接(流)或者面向无连接(数据报)socket上。当socket被socket()函数创建后,它就存在于一个名字空间(地址家族)中,只是它还是未命名的对象。使用bind函数来建立socket的本地关联,它赋值给socket一个本地名称。
当使用Internet地址簇时,一个名字包括三个部分:地址簇,主机地址,端口号,它们代表了一个应用程序。在windows socket2中,名字参数并不是严格的要求是sockaddr指针。为了和windows sockets1兼容,会做一些转换。服务提供者只需要关心name参数是一个指向长度是namelen的内存块即可。这个内存块的开始两个字节必须指出了地址簇(也就是sockaddr的第一个成员u_short sa_family,两个字节长),地址簇用来创建socket。否则,一个WSAEFAULT错误就会产生。
若一个程序并不关心分配给它的本地地址,可以给sockaddr的sa_data字段赋值ADDR_ANY。这样底层网络服务会自动提供可用的地址,这可能简化了多网卡主机的程序的开发。
对于TCP/IP协议而言,若sockaddr的端口字段port赋值的是0,底层服务会自动分配一个从1024到5000的可用端口。程序可以用getsockname来获取系统分配的地址和端口。若指定的地址是ADDR_ANY,getsockname在socket连接之前可能不能提供系统分配的地址,直到有可用的地址为止。客户端程序端口建议指定为0,否则可能指定的端口其他的程序正在使用而发生冲突。
返回值
若调用bind没有错误发生则返回0。否则它返回SOCKET_ERROR,你可以用WSAGetLastError来获取相关的错误码。
错误码
WSANOTINITIALISED 未初始化,请先调用WSAStartup初始化socket。
WSAENETDOWN 网络底层系统错误。
WSAEADDRINUSE 一个进程已经绑定了参数指定的地址和端口。
WSAEADDRNOTAVAIL 指定的地址在本机上不可用。
WSAEFAULT 参数name错误,不属于一个可用的地址空间。namelen太小,name参数包含的地址信息错误,或者name的开始两个字节和地址簇不匹配。
WSAEINPROGRESS 有阻塞的进程,或者windows系统正在调用一个回调函数。
WSAEINVAL socket已经绑定到了一个地址。
WSAENOBUFS 连接太多,没有可用的缓冲区。
WSAENOTSOCK 传入的不是一个socket。
六.sockaddr结构体
sockaddr结构体一定程度上依赖于所选择的协议簇。除了sa_family字段,sockaddr的内容是压缩成网络字节流的。
struct sockaddr{
u_short sa_famly;
char sa_data[14];
};
在windows socket2中,name参数并不是严格的指向sockaddr结构体。这样它可以完成windows socket的兼容。它在不同的协议簇中有不同的意义。仅仅要求的是前两个字节u_short是地址簇,并且总共的内存长度是namelen。
以下的结构体用于TCP/IP协议,其他的协议用法也相似。
struct sockaddr_in{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
注:
一般TCP/IP协议使用sockaddr_in结构体而不是用sockaddr。
sockaddr_in结构体的:
sin_family地址簇字段,一般是AF_INET。
sin_port端口字段,可以用::htons(2000)函数分配指定的端口,hostToNetShort的意思。也可以用sin_port=0来由系统分配可用的端口。
sin_addr地址字段是一个结构体in_addr,它是一个联合体,可以用:sin_addr.s_addr初始化sin_addr字段。而s_addr定义为:#define s_addr S_un.S_addr,也就是一个联合体。对于TCP/IP协议,sin_addr可以指定INADDR_ANY,意味底层协议自动分配地址。若需要指定ip地址,可以用::inet_addr(“10.1.1.1”)来分配指定的地址。
sin_zero是一个0填充,可以用memset(&sockaddr.sin_zero,0,sizeof(sockaddr.sin_zero))。
七.listen函数
windows sockets的listen函数将socket置于侦听状态,它侦听一个传入的连接。
int listen(
SOCKET s,
int backlog
);
参数:
s[in] 一个描述符,指定了一个绑定的、未连接的socket。
backlog[in] 最大的等待队列。若这个值是SOMAXCONN,那么底层服务会为socket分配一个最大的能接受的等待队列。没有提供标准的接口来获得能接受的最大等待队列。
注意:
为了接受连接,一个socket首先要用socket()函数来创建,然后调用bind()函数绑定到一个本地地址,一个backlog由listen来指定,然后传入的连接就可以用accept()来接受了。面向连接的socket,如SOCK_STREAM,是使用listen()函数的。当连接成功建立后,socket被置于“被动”模式。
listen函数典型的用法是在服务器端,它能一次接受多个连接。当一个新连接到达服务器,而等待队列满了,客户端程序会收到一个错误代码WSAECONNREFUSED。
若没有可用的socket描述符,listen函数继续执行。如果描述符可用了,后续的对listen或者accept的调用会重新填充当前队列,或者可能的话,侦听和接受连接。
程序可以在一个socket上多次调用listen函数。这会更新当前socket的等待队列(backlog)。应该指定更多的backlog,否则当前等待的连接会被重置和丢失。
返回值:
若listen调用成功,返回0。否则,返回SOCK_ERROR,可以调用WSAGetLastError函数获取一个错误代码。
错误码:
WSANOTINITIALISED 未初始化socket,请先调用WSAStartup函数。
WSAENETDOWN 底层网络系统错误。
WSAEADDRINUSE socket未绑定到合法的本地地址。
WSAEINPROGRESS 进程被阻塞。
WSAEINVAL socket未调用bind绑定。
WSAEISCONN socket已经处于连接状态。
WSAEMFILE 没有可用的socket描述符。
WSAENOBUFS 没有可用的缓冲。
WSAENOTSOCK 描述符不是一个合法的socket。
WSAEOPNOTSUPP 指向的socket不支持listen操作
Windows sockets函数socket建立一个socket。
SOCKET socket(
int af,
int type,
int protocol
);
参数
af[in] 一个地址簇。
type[in] socket的类型,有SOCK_STREAM和SOCK_DATAGRAM两种类型。
SOCK_STREAM 提供连续的、可靠的、双向的、基于连接的字节流的数据传输机制。使用TCP协议。
SOCK_DATAGRAM 支持数据报,数据报是面向非连接的、不可靠的、大小固定的数据。使用UDP协议。
protocol[in] 使用指定地址簇中的一个特别的协议。
注意
socket函数建立一个socket描述符,底层服务来分配资源和绑定socket。
返回值
若没有错误,socket函数返回一个指向新建的socket的描述符。否则,返回INVALID_SOCKET,你可以用WSAGetLastError函数获取错误码。
错误码
WSANOTINITIALISED 未初始化,请先调用WSAStartup初始化socket。
WSAENETDOWN 网络底层系统错误。
WSAEAFNOSUPPORT 地址簇不支持。
WSAEINPROGRESS 线程被阻塞,或者在回调。
WSAEMFILE socket操作符不可用。
WSAENOBUFS 没有缓冲区可用。
WSAEPROTONOSUPPORT 不支持的协议。
WSAEPROTOTYPE 协议类型错误。
WSAESOCKTNOSUPPORT 协议类型不受地址簇支持。
五.bind函数
Windows sockets函数bind关联一个本地地址到一个socket。
int bind(
SOCKET s,
const struct sockaddr FAR* name,
int namelen
);
参数
s[in] 指明一个未绑定的socket的描述器。
name[in] 将sockaddr指定的地址赋值给socket。
namelen[in] 名称的长度。
注意
bind函数应用在调用connect或者listen函数之前的未连接的socket上。它用于绑定面向连接(流)或者面向无连接(数据报)socket上。当socket被socket()函数创建后,它就存在于一个名字空间(地址家族)中,只是它还是未命名的对象。使用bind函数来建立socket的本地关联,它赋值给socket一个本地名称。
当使用Internet地址簇时,一个名字包括三个部分:地址簇,主机地址,端口号,它们代表了一个应用程序。在windows socket2中,名字参数并不是严格的要求是sockaddr指针。为了和windows sockets1兼容,会做一些转换。服务提供者只需要关心name参数是一个指向长度是namelen的内存块即可。这个内存块的开始两个字节必须指出了地址簇(也就是sockaddr的第一个成员u_short sa_family,两个字节长),地址簇用来创建socket。否则,一个WSAEFAULT错误就会产生。
若一个程序并不关心分配给它的本地地址,可以给sockaddr的sa_data字段赋值ADDR_ANY。这样底层网络服务会自动提供可用的地址,这可能简化了多网卡主机的程序的开发。
对于TCP/IP协议而言,若sockaddr的端口字段port赋值的是0,底层服务会自动分配一个从1024到5000的可用端口。程序可以用getsockname来获取系统分配的地址和端口。若指定的地址是ADDR_ANY,getsockname在socket连接之前可能不能提供系统分配的地址,直到有可用的地址为止。客户端程序端口建议指定为0,否则可能指定的端口其他的程序正在使用而发生冲突。
返回值
若调用bind没有错误发生则返回0。否则它返回SOCKET_ERROR,你可以用WSAGetLastError来获取相关的错误码。
错误码
WSANOTINITIALISED 未初始化,请先调用WSAStartup初始化socket。
WSAENETDOWN 网络底层系统错误。
WSAEADDRINUSE 一个进程已经绑定了参数指定的地址和端口。
WSAEADDRNOTAVAIL 指定的地址在本机上不可用。
WSAEFAULT 参数name错误,不属于一个可用的地址空间。namelen太小,name参数包含的地址信息错误,或者name的开始两个字节和地址簇不匹配。
WSAEINPROGRESS 有阻塞的进程,或者windows系统正在调用一个回调函数。
WSAEINVAL socket已经绑定到了一个地址。
WSAENOBUFS 连接太多,没有可用的缓冲区。
WSAENOTSOCK 传入的不是一个socket。
六.sockaddr结构体
sockaddr结构体一定程度上依赖于所选择的协议簇。除了sa_family字段,sockaddr的内容是压缩成网络字节流的。
struct sockaddr{
u_short sa_famly;
char sa_data[14];
};
在windows socket2中,name参数并不是严格的指向sockaddr结构体。这样它可以完成windows socket的兼容。它在不同的协议簇中有不同的意义。仅仅要求的是前两个字节u_short是地址簇,并且总共的内存长度是namelen。
以下的结构体用于TCP/IP协议,其他的协议用法也相似。
struct sockaddr_in{
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
注:
一般TCP/IP协议使用sockaddr_in结构体而不是用sockaddr。
sockaddr_in结构体的:
sin_family地址簇字段,一般是AF_INET。
sin_port端口字段,可以用::htons(2000)函数分配指定的端口,hostToNetShort的意思。也可以用sin_port=0来由系统分配可用的端口。
sin_addr地址字段是一个结构体in_addr,它是一个联合体,可以用:sin_addr.s_addr初始化sin_addr字段。而s_addr定义为:#define s_addr S_un.S_addr,也就是一个联合体。对于TCP/IP协议,sin_addr可以指定INADDR_ANY,意味底层协议自动分配地址。若需要指定ip地址,可以用::inet_addr(“10.1.1.1”)来分配指定的地址。
sin_zero是一个0填充,可以用memset(&sockaddr.sin_zero,0,sizeof(sockaddr.sin_zero))。
七.listen函数
windows sockets的listen函数将socket置于侦听状态,它侦听一个传入的连接。
int listen(
SOCKET s,
int backlog
);
参数:
s[in] 一个描述符,指定了一个绑定的、未连接的socket。
backlog[in] 最大的等待队列。若这个值是SOMAXCONN,那么底层服务会为socket分配一个最大的能接受的等待队列。没有提供标准的接口来获得能接受的最大等待队列。
注意:
为了接受连接,一个socket首先要用socket()函数来创建,然后调用bind()函数绑定到一个本地地址,一个backlog由listen来指定,然后传入的连接就可以用accept()来接受了。面向连接的socket,如SOCK_STREAM,是使用listen()函数的。当连接成功建立后,socket被置于“被动”模式。
listen函数典型的用法是在服务器端,它能一次接受多个连接。当一个新连接到达服务器,而等待队列满了,客户端程序会收到一个错误代码WSAECONNREFUSED。
若没有可用的socket描述符,listen函数继续执行。如果描述符可用了,后续的对listen或者accept的调用会重新填充当前队列,或者可能的话,侦听和接受连接。
程序可以在一个socket上多次调用listen函数。这会更新当前socket的等待队列(backlog)。应该指定更多的backlog,否则当前等待的连接会被重置和丢失。
返回值:
若listen调用成功,返回0。否则,返回SOCK_ERROR,可以调用WSAGetLastError函数获取一个错误代码。
错误码:
WSANOTINITIALISED 未初始化socket,请先调用WSAStartup函数。
WSAENETDOWN 底层网络系统错误。
WSAEADDRINUSE socket未绑定到合法的本地地址。
WSAEINPROGRESS 进程被阻塞。
WSAEINVAL socket未调用bind绑定。
WSAEISCONN socket已经处于连接状态。
WSAEMFILE 没有可用的socket描述符。
WSAENOBUFS 没有可用的缓冲。
WSAENOTSOCK 描述符不是一个合法的socket。
WSAEOPNOTSUPP 指向的socket不支持listen操作