windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
2010-09-23 20:58
756 查看
别的不多说了,看代码吧。
ECHO服务器端:
测试用客户端,目前地址写在了程序中,用户可以自行修改。
Windows下的编译命令为:
cl -o 服务器程序名称.exe 源文件名称.cpp WS2_32.lib
客户端编译同上,只是修改文件名即可。
ECHO服务器端:
#include <winsock2.h> #include <stdio.h> #include <stdlib.h> #define DEFAULT_PORT 5566 #define BUFFER_SIZE 4096 #define DEFAULT_ADDR_LEN 128 #define MAX_CLIENT (FD_SETSIZE -1) int nPort = DEFAULT_PORT; char szAddr[DEFAULT_ADDR_LEN]; char szBuffer[BUFFER_SIZE]; BOOL bInterface = FALSE; BOOL bEchoBack = FALSE; void usage(void); void checkArgv(int argc, char **argv); BOOL insertSocket(SOCKET *pClient, SOCKET s); int main(int argc, char *argv[]) { WSAData wsaData; WORD wVersion = MAKEWORD(2,2); SOCKET s, sClient; SOCKADDR_IN sa, saRemote; int nRet, nLen, i, nLeft, idx, nRecvLen; SOCKET arrClientSocket[MAX_CLIENT] = {INVALID_SOCKET}; checkArgv(argc, argv); nRet = WSAStartup(wVersion, &wsaData); if (SOCKET_ERROR == nRet) { printf("/nWindows socket startup error:%d/n", WSAGetLastError()); return 1; } printf("Socket initalization...../n"); s = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == s) { printf("/nScoket was created error:%d/n", WSAGetLastError()); return 1; } printf("socket was created/n"); nLen = sizeof(SOCKADDR_IN); memset(&sa, 0, nLen); sa.sin_family = AF_INET; sa.sin_port = htons(nPort); if (bInterface) { sa.sin_addr.s_addr = inet_addr(szAddr); } else { sa.sin_addr.s_addr = htonl(INADDR_ANY); } nRet = bind(s, (LPSOCKADDR)&sa, nLen); if (SOCKET_ERROR == nRet) { printf("Socket bind error:%d/n", WSAGetLastError()); return 1; } printf("bind was successed/n"); nRet = listen(s, 8); if (SOCKET_ERROR == nRet) { printf("Socket listen error:%d/n", WSAGetLastError()); return 1; } printf("listen was successed/n"); fd_set fdRead; for(i = 0;i < MAX_CLIENT; i++) { arrClientSocket[i] = INVALID_SOCKET; } for(;;) { //初始化队列,将所有套接字加入。 FD_ZERO(&fdRead); FD_SET(s, &fdRead); for(i = 0; i < MAX_CLIENT; i++) { if (INVALID_SOCKET != arrClientSocket[i]) { FD_SET(arrClientSocket[i], &fdRead); } } nRet = select(0, &fdRead, NULL, NULL, NULL); if (SOCKET_ERROR == nRet) { printf("/nSelect() error:%d/n", WSAGetLastError()); break; } if (nRet > 0) { //说明有新SOCKET连接到服务器 if(FD_ISSET(s, &fdRead)) { sClient = accept(s, (LPSOCKADDR)&saRemote, &nLen); insertSocket(arrClientSocket, sClient); printf("Sokcet:%d, was accept()/n", sClient); continue; } for(i = 0; i < MAX_CLIENT; i++) { if (FD_ISSET(arrClientSocket[i], &fdRead)) { memset(szBuffer, 0, BUFFER_SIZE); nRet = recv(arrClientSocket[i], szBuffer, BUFFER_SIZE, 0); if (nRet <= 0) { closesocket(arrClientSocket[i]); arrClientSocket[i] = INVALID_SOCKET; continue; } nRecvLen = nRet; printf("Socket:%d, %d, send data:%s/n", arrClientSocket[i], nRet, szBuffer); if (!bEchoBack) { nRet = getpeername(arrClientSocket[i], (LPSOCKADDR)&saRemote, &nLen); if (SOCKET_ERROR == nRet) { printf("/ngetpeername() error:%d/n", WSAGetLastError()); continue; } nLeft = nRecvLen; idx = 0; while (nLeft > 0) { nRet = send(arrClientSocket[i], &szBuffer[idx], nLeft, 0); if (0 == nRet) break; else if (SOCKET_ERROR == nRet) { printf("Send() failed:%d/n", WSAGetLastError()); break; } nLeft -= nRet; idx += nRet; } } } } } } closesocket(s); WSACleanup(); return 0; } void usage(void) { printf("usage: selectecho.exe [-p:5566] [-i:127.0.0.1] [-o]/n/n"); printf("/t-p:监听的端口号, 在1024到65535之间/n"); printf("/t-i:监听的服务器地址/n"); printf("/t-o:是否将数据发回客户端/n/n"); ExitProcess(1); } void checkArgv(int argc, char **argv) { int i; for(i = 1; i < argc; i++) { if(('/' == argv[i][0]) || ('-' == argv[i][1])) { switch(tolower(argv[i][1])) { case 'p': nPort = atoi(&argv[i][3]); break; case 'i': memset(szAddr, 0, DEFAULT_ADDR_LEN); strcpy(szAddr, &argv[i][3]); bInterface = TRUE; break; case 'o': bEchoBack = TRUE; break; default: usage(); break; } } } } BOOL insertSocket(SOCKET *pClient, SOCKET s) { int i; BOOL bResult = FALSE; for(i = 0; i < MAX_CLIENT; i++) { if (INVALID_SOCKET == pClient[i]) { pClient[i] = s; bResult = TRUE; break; } } return bResult; }
测试用客户端,目前地址写在了程序中,用户可以自行修改。
#include <stdio.h> #include <stdlib.h> #include <winsock2.h> #define SERVER_PORT 5566 #define BUFFER_SIZE 4096 #define MAX_ADDR_LEN 128 int nPort = SERVER_PORT; char szBuffer[BUFFER_SIZE]; char szAddr[MAX_ADDR_LEN]; void usage(void); void checkArgv(int argc, char **argv); int main(int argc, char *argv[]) { int nRet, nLen, nAddrLen, i; SOCKET s; SOCKADDR_IN sa; WSAData wsaData; WORD wVersion = MAKEWORD(2,2); checkArgv(argc, argv); nRet = WSAStartup(wVersion, &wsaData); if (SOCKET_ERROR == nRet) { printf("Socket init error/n"); return 1; } s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == s) { printf("Socket was created failse:%d/n", WSAGetLastError()); closesocket(s); WSACleanup(); return 1; } nAddrLen = sizeof(SOCKADDR_IN); memset(&sa, 0, nAddrLen); sa.sin_family = AF_INET; sa.sin_port = htons(nPort); sa.sin_addr.s_addr = inet_addr("127.0.0.1"); nRet = connect(s, (LPSOCKADDR)&sa, nAddrLen); if (SOCKET_ERROR == nRet) { printf("socket connect() failse:%d/n", WSAGetLastError()); closesocket(s); WSACleanup(); return 1; } for(;;) { printf("/nSend Message to ECHO:"); memset(szBuffer, 0, BUFFER_SIZE); nRet = scanf("%s", szBuffer); if (BUFFER_SIZE < nRet) { szBuffer[BUFFER_SIZE-1] = '/0'; } if (0 == strcmp("quit",szBuffer)) break; //输入QUIT退出当前客户端 nRet = send(s, szBuffer, strlen(szBuffer), 0); if (SOCKET_ERROR == nRet) { printf("Socket send() failse:%d/n", WSAGetLastError()); break; } memset(szBuffer, 0, BUFFER_SIZE); nRet = recv(s, szBuffer, BUFFER_SIZE, 0); printf("Server ECHO back:%s/n", szBuffer); } closesocket(s); WSACleanup(); return 0; } void usage(void) { printf("usage: selectecho.exe -i:127.0.0.1 [-p:5566]/n"); printf("/t-i:服务器地址/n"); printf("/t-p:服务器端口号, 在1024到65535之间/n"); ExitProcess(1); } void checkArgv(int argc, char **argv) { int i; memset(szAddr, 0, MAX_ADDR_LEN); for(i = 1; i < argc; i++) { if(('/' == argv[i][0]) || ('-' == argv[i][1])) { switch(tolower(argv[i][1])) { case 'p': nPort = atoi(&argv[i][3]); break; case 'i': strcpy(szAddr, &argv[i][3]); printf("%s", argv[i][3]); break; default: usage(); break; } } } }
Windows下的编译命令为:
cl -o 服务器程序名称.exe 源文件名称.cpp WS2_32.lib
客户端编译同上,只是修改文件名即可。
相关文章推荐
- windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
- windows下的网络编程——Select模型实例,一款ECHO服务的实现代码
- [Windows]7种网络编程I/O模型代码实现实例
- 7种网络编程I/O模型代码实现实例
- 7种网络编程I/O模型代码实现实例
- 7种网络编程I/O模型代码实现实例
- 7种网络编程I/O模型代码实现实例
- 基于visual c++之windows核心编程代码分析(33)实现防火墙模型
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll、Epoll模型处理长连接性能比较
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较
- 实例分析之用ASP编程实现网络内容快速查找的代码
- 从零实现一个最精简的select网络服务模型
- Windows网络编程之Select模型学习笔记
- java udp网络编程及实例代码,实现客户端和服务端通信
- windows网络编程之select模型(改进)
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll、Epoll模型处理长连接性能比较
- Linux网络编程select模型的实现
- 网络编程:select模型的简单实例
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——朴素模型
- Linux网络编程select模型的实现