Winsocket入门教程三:以Windows消息机制驱动的客户端程序

     前面两讲为大家介绍了编写传统socket程序的两种方法,今天将为大家介绍一种使用Windows消息机制编写socket客户端程序的方法。使用Windows消息机制编写socket程序主要有以下的好处:一是我们可以将大部分的recv操作以及close操作放到消息处理函数里面,以利于代码的维护;二是当有数据可读的时候,本地程序会接到相应的消息,我们可以在这时候读取数据。大家可以想像一下,在传统的socket程序中,如果一个远程程序在你没有向它发送请求的时候给你传送数据的话,如果本地程序没有进行相应的检测(一种方法是通过计时器进行检测),是不能及时根据它发送给你的数据进行相应的操作的。而如果使用消息机制的话,就能很好的解决这个问题;三是可以轻松的检测出远程程序主动关闭和意外退出的情况。如果使用传统方式的话,我们必须定时进行相应的检测才能知道该情况的发生。

     为了使用消息机制驱动的网络程序,我们必须使用WSAAsyncSelect函数注册Windows消息以及我们感兴趣的网络事件。WSAAsyncSelect函数的函数原型如下所示:

      int WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent)

      s
[in] 需要获取相应网络事件的套接字。
      hWnd           [in] 需要获取相应网络事件的窗口。       wMsg           [in] 当网络事件发生时候将会收到的消息。       lEvent           [in] 可以使用位域组合的网络事件。      Return Values           成功返回0,失败返回SOCKET_ERROR。在返回SOCKET_ERROR的时候,你可以使用WSAGetLastError来获取相应的错误代码。            做为一个客户端程序,我们主要对以下Winsocket中定义的网络事件感兴趣。      FD_CONNECT           当连接完成的时候希望收到我们注册的网络消息。      FD_READ           当有数据可读时希望收到我们注册的网络消息。      FD_WRITE            当可以向对方写数据时希望收到我们注册的网络消息。      FD_CLOSE            当套接字关闭的时候希望收到我们注册的网络消息。            假设我们已经在应用程序中创建了套接字s,获取了窗口句柄hwnd以及定义了WM_SOCKET消息,我们可以按照如下的方式调用WSAAsyncSelect函数,以使我们可以在有数据可读和套接字关闭的时候收到WM_SOCKET消息。             但我们需要注意的是,如果对同一个套
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,这是一个经典的 Socket 编程问题,我可以为您提供一些基本的思路和代码示例。 首先,服务客户都需要创建一个 Socket 对象,以便进行通信。在 C 语言中,可以使用 Winsock 库来实现 Socket 编程。以下是服务客户的代码示例。 服务代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <winsock2.h> int main() { // 初始化 Winsock 库 WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); return 1; } // 创建 Socket 对象 SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listenSocket == INVALID_SOCKET) { printf("Error creating socket: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } // 绑定 Socket 对象到本地地址和口 struct sockaddr_in localAddr; localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = INADDR_ANY; localAddr.sin_port = htons(12345); iResult = bind(listenSocket, (struct sockaddr*) &localAddr, sizeof(localAddr)); if (iResult == SOCKET_ERROR) { printf("Bind failed: %d\n", WSAGetLastError()); closesocket(listenSocket); WSACleanup(); return 1; } // 开始监听客户连接请求 iResult = listen(listenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("Listen failed: %d\n", WSAGetLastError()); closesocket(listenSocket); WSACleanup(); return 1; } // 等待客户连接 printf("Waiting for client connection...\n"); SOCKET clientSocket = accept(listenSocket, NULL, NULL); if (clientSocket == INVALID_SOCKET) { printf("Accept failed: %d\n", WSAGetLastError()); closesocket(listenSocket); WSACleanup(); return 1; } // 接收和发送数据 char recvBuf[1024]; char sendBuf[1024]; while (1) { // 接收客户发来的数据 iResult = recv(clientSocket, recvBuf, sizeof(recvBuf), 0); if (iResult > 0) { recvBuf[iResult] = '\0'; printf("Received: %s\n", recvBuf); // 发送数据给客户 sprintf(sendBuf, "Hello, %s!", recvBuf); iResult = send(clientSocket, sendBuf, strlen(sendBuf), 0); if (iResult == SOCKET_ERROR) { printf("Send failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } } else if (iResult == 0) { printf("Connection closed.\n"); break; } else { printf("Recv failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } } // 关闭 Socket 对象 closesocket(clientSocket); closesocket(listenSocket); WSACleanup(); return 0; } ``` 客户代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <winsock2.h> int main() { // 初始化 Winsock 库 WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); return 1; } // 创建 Socket 对象 SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (clientSocket == INVALID_SOCKET) { printf("Error creating socket: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } // 连接到服务 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(12345); iResult = connect(clientSocket, (struct sockaddr*) &serverAddr, sizeof(serverAddr)); if (iResult == SOCKET_ERROR) { printf("Connect failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } // 接收和发送数据 char recvBuf[1024]; char sendBuf[1024]; while (1) { // 发送数据给服务 printf("Enter message: "); fgets(sendBuf, sizeof(sendBuf), stdin); sendBuf[strlen(sendBuf)-1] = '\0'; iResult = send(clientSocket, sendBuf, strlen(sendBuf), 0); if (iResult == SOCKET_ERROR) { printf("Send failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } // 接收服务发来的数据 iResult = recv(clientSocket, recvBuf, sizeof(recvBuf), 0); if (iResult > 0) { recvBuf[iResult] = '\0'; printf("Received: %s\n", recvBuf); } else if (iResult == 0) { printf("Connection closed.\n"); break; } else { printf("Recv failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } } // 关闭 Socket 对象 closesocket(clientSocket); WSACleanup(); return 0; } ``` 以上代码示例只是基本的实现,您可以根据自己的需要进行进一步的修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值