winsock编程(四)

 八.accept函数
windows sockets的accept函数接受一个传入的连接。

SOCKET accept(

SOCKET s,

struct sockaddr FAR* addr,

int FAR* addrlen

);

参数:
s[in] 一个描述符指定一个调用了listen函数处于listening状态的socket,在accept返回一个客户端socket后,连接将会真正建立。

addr[out] 一个优化了的指针指向一个缓冲区,它获取了传入的连接对象的地址信息。当连接建立,并且socket创建后,addr的格式就由地址簇确定了。

addrlen[out] 一个优化的指针,包含了地址addr的长度。

注意:
accept函数取出s的等待队列上的第一个连接。然后accept函数将建立一个新socket并返回一个指向这个新socket的句柄。新建立的socket将会处理实际的连接,并和s有相同的属性,属性包括异步通信用WSASelect和WSAEventSelect注册的事件。s并未有侦听的socket的groupId,即便要做相关处理。

accept将会阻塞调用者,直到一个新的连接传入;若在s的等待队列中没有出现新连接,socket将会标记未阻塞。若socket未标记为阻塞,而等待队列中没有可用的连接,accept返回一个下面描述的错误码。在accept成功返回一个新的socket句柄后,返回的socket不能用于接受连接,而原来的s则还是打开并侦听新的连接。

参数addr是一个结果参数,它将会由建立的连接实体的地址填充。addr的格式在连接建立时将由地址簇确定。addrlen是一个值结果,它应该初始化为addr分配的总空间,在返回时它将包含实际的地址的字节长度。

accept用于面向连接的socket,如SOCK_STREAM。

若addr和/或addrlen为NULL,则不会返回任何远程socket地址信息。

返回值:
若调用成功,返回一个socket描述符。返回值是一个句柄,实际的连接将建立在这个句柄上。

否则,返回INVALID_SOCKET,可以用WSAGetLastError获取一个错误码。

指向初始的socketaddr的整型指针,赋值为addr的大小;返回时,它将指向实际的地址的字节大小。

错误码:
WSANOTINITIALISED 未初始化socket,请先调用WSAStartup函数。

WSAENETDOWN 底层网络系统错误。

WSAEFAULT addrlen太小或者addr指向的空间并可用。

WSAEINTR 阻塞被调用WSACanceBlockingCall取消。

WSAEINPROGRESS 进程被阻塞,或者正在回调中。

WSAEINVAL 在调用accept之前未调用listen。

WSAEMFILE 队列不为空但没有可用的socket描述符。

WSAENOBUFS 缓冲不可用。

WSAENOTSOCK 描述符不是可用的socket。

WSAEOPNOTSUPP 指向的socket不支持面向连接的服务。

WSAEWOULDBLOCK socket被标记为非阻塞,但没有可用的等待连接。

九.connect函数
windows sockets函数connect建立一个到确定的socket的连接。

int connect(

SOCKET s,

const struct sockaddr FAR* name,

int namelen

);

参数:
s[in] 一个指向未连接的socket。

name[in] 要连接的socket名称。

namelen[in] name参数的长度。

注意:
connect函数用来建立一个到目的地的连接。若socket s未绑定,系统将会给它赋一个唯一的值并且和本机关联,系统也将把这个socket标记为已绑定。

对于面向连接(如SOCK_STREAM)的socket,一个活动的连接初始化为外部主机名(一个socket的地址空间,详细信息请参考bind函数)。当socket调用完全成功后,它就准备接受或者发送数据了。若由name参数确定的地址成员为0,connect会返回错误WSAEADDRNOTAVAIL。所有尝试重新连接到一个活动的连接会返回失败,错误代码是WSAEISCONN。

对于面向连接、非阻塞的socket通常不会立即完成连接。在这种情况下,connect函数会返回错误WSAEWOULDBLOCK。尽管这样,操作还是进行了。当操作成功或者失败的结果知道后,它将会按照注册的事件通知客户端。若客户端使用select函数,成功的结果将会保存到writefds,错误结果将会保存到exceptfds中,并且错误代码FD_CONNECT指出是否调用成功或者失败的原因。

对于面向非连接(如SOCK_DGRAM),connect执行的操作只不过是为了建立一个默认的目的地址,这个地址将用在随后的send/WSASend和recv/WSARecv调用中。从任何除了目的地址的地址收到的数据报都会被丢弃。若由参数name传入的地址成员为0,则socket会“断开连接”。远程地址也会成为不明确的,所以send/WSASend和recv/WSARecv调用将返回错误码WSAENOTCONN。尽管这样,sendto/WSASendTo和recvfrom/WSARecvFrom还是可以调用。默认的目的地地址能再次调用connect而改变,尽管socket已经连接了。所有名字和当前连接的名字不同的数据报都会丢弃。

对于面向非连接的socket,name参数能指出合法地址,包括广播地址。尽管这样,为了连接到一个广播网络,socket必须调用setsocketopt来启用SO_BROADCAST选项。否则,connect函数返回错误码WSAEACCESS。

当socket之间的连接被中断,socket应当丢弃并且销毁。若在已经连接的socket上发现问题,程序应该丢弃这个socket,并重新建立socket来连接到稳定的端点。

返回值:
若没有错误则返回0,否则返回SOCK_ERROR,可以用WSAGetLastError获取最后的错误代码。

对于阻塞的socket,返回值指出操作的结果是成功或者失败。

对于非阻塞的socket,连接尝试可能不会立即完毕。在这种情况下,connect返回SOCK_ERROR,WSAGetLastError将获取WSAEWOULDBLOCK,你可以有三个不同的选择:

1.使用select函数检测是否连接已经完成,查看是否socket可写。

2.若程序使用WSAAsyncSelect指出感兴趣的事件,那么程序将会收到一个FD_CONNECT通知和来指出connect操作已经完成了。

3.若程序使用WSAEventSelect指出感兴趣的事件,则关联的事件对象会收到connect操作完毕的消息。

直到连接尝试完毕一个非阻塞的socket,所有后续在同样的socket上调用connect都会失败,错误代码是WSAEALREADY和WSAEISCONN在连接完毕。由于在windows sockets规范1.1版本中的含糊不清,返回的错误代码将会有所变动。所以,并不推荐程序使用多次调用连接来检测连接是否完成。如果这样做,必须处理WSAEINVAL和WSAEWOULDBLOCK错误代码,同样的方式他们要处理WSAEALREADY来保证程序的健壮性。

如果错误代码指出连接尝试失败(这些错误代码是WSAECONNREFUSED,WSAENETUNREACH,WSAETIMEOUT),程序可以对同样的socket重新调用connect。

错误码:
WSANOTINITIALISED 未初始化socket,请先调用WSAStartup函数。

WSAENETDOWN 底层网络系统错误。

WSAEADDRINUSE socket地址正在使用。

WSAEINTR 线程取消阻塞,WSACancelBlocking被调用。

WSAEINPROGRESS 线程被阻塞,或者正在回调。

WSAEALREADY 一个非阻塞的connect调用了。

WSAEADDRNOTAVAIL 远程地址非法。

WSAEAFNOSUPPORT 地址簇不能用在当前socket上。

WSAECONNREFUSED 被迫终止连接。

WSAEFAULT name或者namelen不是可用的地址空间。

WSAEINVAL 参数socket是一个正在侦听的socket。

WSAEISCONN socket已经连接了。

WSAENETUNREACH 当起主机不能连接网络。

WSAENOBUFS 缓冲不可用。

WSAENOTSOCK 描述符不是一个socket。

WSAETIMEDOUT 未建立连接的情况下尝试超时。

WSAEWOULDBLOCK socket被标记为非阻塞,连接不能立即完成。

WSAEACCES 尝试连接数据报socket到广播网络,但没有用setsockopt未允许SO_BROADCAST未开启
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值