1.2.1 流式套接字编程(www.cppentry.com)(3)
2.客户端编程(www.cppentry.com)步骤
(1) 建立客户端的Socket
客户端应用程序首先也是调用WSAStartup()函数来与Winsock的动态链接库建立关系,然后同样调用socket()来建立一个TCP或UDP Socket(相同协定的Sockets才能相通,TCP对TCP,UDP对UDP)。与服务器端的Socket不同的是,客户端的Socket可以调用 bind()函数,由自己来指定IP地址及port号码;但是也可以不调用bind(),而由Winsock来自动设定IP地址及port号码。
(2) 提出连接请求
客户端的Socket使用connect()函数来提出与服务器端的Socket建立连接的申请,函数调用成功返回0,否则返回SOCKET_ERROR:
- int connect(
- SOCKET s, //服务器端Socket的识别码
- const struct sockaddr FAR *name, //Socket想要连接的对方地址
- int namelen //地址长度
- );
作为客户端的监控程序,其实现过程要比服务器简单许多。由于需要接收数据,因此在异步选择函数中需要设定待监测的网络事件为FD_CLOSE和FD_READ。在消息响应函数中可以通过对消息参数的低位字节进行判断而区分出具体发生的是何种网络事件,并对其做出相应的反应。
3.数据的传送
基于TCP/IP连接协议(流式套接字)的服务是设计客户机/服务器应用程序时的主流标准,但有些服务是可以通过无连接协议(数据报套接字)提供的。一般情况下TCP Socket的数据发送和接收是调用send()及recv()这两个函数来达成,而UDP Socket则是用sendto()及recvfrom()这两个函数,这两个函数调用成功返回发送或接收的资料的长度,否则返回SOCKET_ERROR。send()函数的原型如下:
- int send(
- SOCKET s, //Socket的识别码
- const char FAR *buf, //存放要传送的资料的暂存区
- int len, //buf的长度
- int flags //此函数被调用的方式
- );
对于Datagram Socket而言,若是Datagram的大小超过限制,则将不会送出任何资料,并会传回错误值。对Stream Socket而言,在Blocking模式下,若是传送系统内的存储空间不够存放这些要传送的资料,send()将会被block住,直到资料送完为止;如果该Socket被设定为 Non-Blocking模式,那么将视目前的output buffer空间有多少,就送出多少资料,并不会被block住。
flags的值可设为0或MSG_DONTROUTE及MSG_OOB的组合。
recv()函数的原型如下:
- int recv(
- SOCKET s, // Socket的识别码
- char FAR *buf, // 存放接收到资料的暂存区
- int len, // buf的长度
- int flags; // 此函数被调用的方式
- );