- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
// 关闭 Socket
// printf("Closing socket number %d\n", SI->Socket); // 释放指定 LPSOCKET_INFORMATION 对象资源
GlobalFree(SI); // 将数组中 Index 索引后面的元素前移
for (i = Index; i < TotalSockets; i++) {
8.3.2 基于 Select 模型的服务器应用程序实例
本节将通过一个实例演示基于 Select 模型的服务器应用程序的设计方法。 【例 8.4】 设计一个基于 Select 模型的回显服务器应用程序。所谓回显,即将它收到的来自 客户端的字符串再发送回客户端。假定本实例中的项目名称为 SelectServer。
void FreeSocketInformation(DWORD Index) {
// 获取指定索引对应的 LPSOCKET_INFORMATION 对象
LPSOCKET_INFORMATION SI = SocketArlosesocket(SI->Socket);
1.结构体 SOCKET_INFORMATION 结构体 SOCKET_INFORMATION 用于记录服务器与每个客户端之间进行通信的信息,代码 如下。
typedef struct _SOCKET_INFORMATION {
CHAR Buffer[DATA_BUFSIZE];// 发送和接收数据的缓冲区
常量 FD_SETSIZE 等于 64,因为默认情况下 select()函数最多可以处理 64 个套接字。 3.创建 Socket 信息 调用 CreateSocketInformation()函数可以为指定的 Socket 创建对应的 SOCKET_INFORMATION 结构体,并将其添加到 SocketArray 数组中,代码如下。
SocketArray[i] = SocketArray[i+1]; } TotalSockets--;
// Socket 总数减
}
5.主函数_tmain()中的变量定义 因为主函数_tmain()的代码比较多,所以这里对其进行分块介绍。_tmain()函数中声明的变量 如下。
200
int _tmain(int argc, _TCHAR* argv[])
第 8 章 高级 Socket 编程技术
• FD_CLR(s, *set):从集合中删除指定的 Socket。 • FD_ISSET(s, *set):如果参数 s 是集合中的成员,则返回非 0 值,否则返回 0。 • FD_SET(s, *set):向集合中添加 Socket。 • FD_ZERO(s, *set):将集合初始化为空集合。
{ printf("GlobalAlloc() failed with error %d\n", return FALSE;
} // 初始化 SI 的值
SI->Socket = s; SI->BytesSEND = 0; SI->BytesRECV = 0; // 在 SocketArray 数组中增加一个新元素,用于保存 SI 对象
WSABUF DataBuf;
// 定义发送和接收数据缓冲区的结构体,包括缓冲区的长度和内容
SOCKET Socket;
// 与客户端进行通信的 Socket
DWORD BytesSEND;
// 保存 Socket 发送的字节数
DWORD BytesRECV;
// 保存 Socket 接收的字节数
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
// 缓冲区的长度 // 指向缓冲区的指针
2.变量定义 为了对所有与客户端进行通信的 Socket 信息进行统一管理,需要定义下面两个变量。
// 记录正在使用的套接字总数量 DWORD TotalSockets = 0; // 保存 Socket 信息对象的数组,FD_SETSIZE 表示 SELECT 模型中允许的最大 Socket 数量 LPSOCKET_INFORMATION SocketArray[FD_SETSIZE];
BOOL CreateSocketInformation(SOCKET {
LPSOCKET_INFORMATION SI; // 为 SI 分配内存空间
s) // 用于保存 Socket 的信息
199
Windows 网络编程(第 2 版)
if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION))) == NULL)
结构体 SOCKET_INFORMATION 中包含用于通信的 Socket、发送和接收数据的缓冲区、发 送和接收的字节数等。
WSABUF 是 winsock2.h 中定义的结构体,用于保存缓冲区的地址和长度,代码如下。
typedef struct _WSABUF { u_long len;
char FAR * buf; } WSABUF, FAR * LPWSABUF;
FD_SET WriteSet;
SocketArray[TotalSockets] = SI; TotalSockets++;
// 增加 Socket 数量
GetLastError());
returnTRUE; }
4.释放 Socket 信息 调用 FreeSocketInformation()函数可以删除指定 Socket 对应的 SOCKET_INFORMATION 结构 体,并关闭该 Socket,代码如下。
{ SOCKET ListenSocket;
// 监听 Socket
SOCKET AcceptSocket;
// 与客户端进行通信的 Socket
SOCKADDR_IN InternetAddr;
// 服务器的地址
WSADATA wsaData;
// 用于初始化 Socket 环境
INT Ret;
// WinSock API 的返回值