基于Socket的select消息传递实践教程

需积分: 5 0 下载量 10 浏览量 更新于2024-10-31 收藏 53KB RAR 举报
资源摘要信息:"WinSock_MsgSnd.rar" 知识点概述: 本压缩包内含两个文件,"MsgSndClnt"和"MsgSndSrv",分别代表客户端和服务器端的程序代码,用于实现基于WinSock的Socket通信。Socket通信是网络编程的核心部分,允许不同主机上的应用程序通过网络进行数据交换。本例中,服务器端采用select模型进行非阻塞式的客户端数据处理,这是多线程编程模式之外的一种常见且高效的处理方式。下面将对WinSock、Socket通信、select模型进行详细介绍。 1. WinSock(Windows Sockets): WinSock是Windows平台上实现Socket通信的一套API,它提供了一种标准的网络编程接口,用于开发基于TCP/IP协议族的应用程序。Windows Sockets规范基于BSD套接字,它是UNIX下网络通信的标准接口。WinSock分为两个版本,Winsock 1主要提供基本的网络通信功能,而Winsock 2在前者的基础上进行了扩展,提供更多的通信协议支持和异步操作接口。 2. Socket通信: Socket是一种编程接口,允许程序之间通过网络传输数据。在TCP/IP网络模型中,Socket是实现传输层通信的基本方式。Socket编程主要涉及两个端点的创建:服务器端Socket和客户端Socket。服务器端Socket监听指定端口,等待客户端的连接请求;客户端Socket发起连接请求,连接到服务器端。一旦连接建立,就可以通过Socket读写数据,实现双方通信。 3. socket套接字: 套接字(Socket)是网络通信的基本单元,可以看作是网络通信中的一个端点。它存在于网络通信的任何一端,是网络编程的核心对象。在C/C++等语言中,Socket被表示为一个文件描述符(在类UNIX系统中)或一个句柄(在Windows系统中),通过这个描述符或句柄,程序可以进行数据的发送和接收操作。 4. select模型: select模型是Unix/Linux下一种I/O多路复用技术,允许程序监视多个文件描述符,等待一个或多个描述符成为就绪状态,从而进行数据读写操作。这种方式能够提高程序处理效率,尤其是当程序需要处理多个网络连接时。在Windows平台上,select函数同样存在,但其性能不如基于IOCP(I/O Completion Ports)模型。然而,select模型因其简单性,在小型或学习性质的项目中仍然广泛使用。 5. 服务器端与客户端的实现: 在本例的"MsgSndSrv"服务器端代码中,实现了一个基础的select监听机制,它能够处理多个客户端的连接请求和数据接收。服务器程序会监听一个或多个端口,当有客户端请求连接时,服务器接受连接,并将其加入到select监听的文件描述符集合中。使用select函数等待任何一个或多个描述符变为可读状态,然后对可读描述符进行数据接收处理。 6. 客户端实现: 客户端程序"MsgSndClnt"负责与服务器建立连接,并发送数据。客户端使用socket函数创建一个套接字,然后通过connect函数连接到服务器的IP地址和端口。连接成功后,客户端就可以通过send或recv函数发送或接收数据。 总结: WinSock_MsgSnd.rar提供的示例代码展示了如何使用WinSock API在Windows环境下通过socket进行通信,并利用select模型进行高效的客户端数据处理。该示例适用于学习和实践基本的网络编程概念和方法,并可以帮助开发者理解和掌握TCP/IP通信、Socket编程和I/O多路复用技术。

客户端代码 #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <stdio.h> #include <Winsock2.h> #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #pragma comment(lib,"ws2_32.lib") int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1, 1); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return -1; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); send(sockClient, "hello\0", strlen("hello") + 1, 0); char recvBuf[50]; recv(sockClient, recvBuf, 50, 0); printf("%s\n", recvBuf); closesocket(sockClient); WSACleanup(); return 0;} 服务器端:#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <stdio.h> #include <Winsock2.h> #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #pragma comment(lib,"ws2_32.lib") int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return 1; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { WSACleanup(); return 1; } SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); int optval = 1; setsockopt(sockSrv, SOL_SOCKET, SO_REUSEADDR, (const char*)&optval, sizeof(optval)); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); listen(sockSrv, 5); SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); while (1) { SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len); char sendBuf[50]; printf(sendBuf, "Welcome %s to here!", inet_ntoa(addrClient.sin_addr)); send(sockConn, sendBuf, strlen(sendBuf) + 1, MSG_NOSIGNAL); char recvBuf[50]; recv(sockConn, recvBuf, 50, 0); printf("%s\n", recvBuf); closesocket(sockConn); } WSACleanup(); return 0;} 如何修改代码改成可以一直聊天的 不要预输入进去的 要我自己在客户端进行打字操作

2023-06-06 上传