windows socket 通信问题
今天看了《C++ 揭秘与防范黑客编程》(作者: 翼云),看了2.4节的程序后,自己写了一下。
客户端:
main.cpp
1 //file name: main.cpp 2 3 #include <WinSock2.h> 4 #include <iostream> 5 #include <assert.h> 6 7 #pragma comment(lib, "ws2_32") 8 9 using namespace std; 10 11 //存储系统信息的结构体 12 typedef struct _SYS_INFO 13 { 14 char m_szComputerName[MAXBYTE]; 15 char m_szUserName[MAXBYTE]; 16 OSVERSIONINFO m_sVer; 17 }SYS_INFO, *PSYS_INFO; 18 19 void ShowSysInfo( PSYS_INFO pInfo ) 20 { 21 assert(NULL != pInfo); 22 23 if (VER_PLATFORM_WIN32_NT == pInfo->m_sVer.dwPlatformId) 24 { 25 if (5==pInfo->m_sVer.dwMajorVersion) 26 { 27 switch (pInfo->m_sVer.dwMinorVersion) 28 { 29 case 1: 30 cout<<"Windows XP"; 31 break; 32 case 0: 33 cout<<"Windows 2000"; 34 break; 35 case 2: 36 cout<<"Windows Server 2003"; 37 break; 38 } 39 } 40 if (6==pInfo->m_sVer.dwMajorVersion) 41 { 42 switch (pInfo->m_sVer.dwMinorVersion) 43 { 44 case 1: 45 cout<<"Windows 7"; 46 break; 47 case 0: 48 cout<<"Windows Server 2008 or Windows Vista"; 49 break; 50 } 51 } 52 cout<<" "<<pInfo->m_sVer.szCSDVersion<<endl; 53 } 54 else 55 { 56 cout<<"Other System"<<endl; 57 } 58 cout<<"Computer Name: "<<pInfo->m_szComputerName<<endl; 59 cout<<"User Name: "<<pInfo->m_szUserName<<endl; 60 } 61 62 int main(int argc, char *argv) 63 { 64 //初始化ws2_32.dll 65 WSADATA wsaData; 66 if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) 67 { 68 cout<<"初始化ws2_32.dll时出错,错误号为: "<<WSAGetLastError()<<endl; 69 return -1; 70 } 71 72 //创建套接字 73 SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 74 if (INVALID_SOCKET == s) 75 { 76 cout<<"创建套接字时出错,错误号为: "<<WSAGetLastError()<<endl; 77 goto ERR0; 78 } 79 sockaddr_in sockAddr; 80 sockAddr.sin_family = PF_INET; 81 sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 82 sockAddr.sin_port = htons(827); 83 84 //建立连接 85 if (SOCKET_ERROR == connect(s, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR))) 86 { 87 cout<<"建立连接时出错,错误号为: "<<WSAGetLastError()<<endl; 88 goto ERR; 89 } 90 91 //接收和发送数据 92 char szBuffer[1024] = {0}; 93 char szCmd[MAXBYTE] = {0}; 94 while (true) 95 { 96 memset(szBuffer, 0, 1024); 97 memset(szCmd, 0, MAXBYTE); 98 99 int nRecv = recv(s, szBuffer, 1024, NULL); 100 if (0 == nRecv) 101 { 102 cout<<"连接已经被关闭"<<endl; 103 goto ERR; 104 } 105 if (SOCKET_ERROR == nRecv) 106 { 107 cout<<"接收数据时出错,错误号为: "<<WSAGetLastError()<<endl; 108 goto ERR; 109 } 110 cout<<szBuffer; 111 112 cin>>szCmd; 113 int nSend = send(s, szCmd, MAXBYTE, NULL); 114 if (SOCKET_ERROR == nSend) 115 { 116 cout<<"发送数据时出错,错误号为: "<<WSAGetLastError()<<endl; 117 goto ERR; 118 } 119 120 memset(szBuffer, 0, 1024); 121 nRecv = recv(s, szBuffer, 1024, NULL); 122 if (0 == nRecv) 123 { 124 cout<<"连接已经被关闭"<<endl; 125 goto ERR; 126 } 127 if (SOCKET_ERROR == nRecv) 128 { 129 cout<<"接收数据时出错,错误号为: "<<WSAGetLastError()<<endl; 130 goto ERR; 131 } 132 133 if (0 == strcmp(szCmd, "getsysinfo")) 134 { 135 PSYS_INFO pInfo = (PSYS_INFO)szBuffer; 136 137 ShowSysInfo(pInfo); 138 } 139 else 140 { 141 cout<<szBuffer<<endl; 142 } 143 } 144 145 ERR: 146 closesocket(s); 147 ERR0: 148 WSACleanup(); 149 150 return 0; 151 }
服务器端:
control.h
//file name: control.h #pragma once #include <WinSock2.h> #pragma comment(lib, "ws2_32") #pragma comment(lib, "winmm.lib") #define DISPATH_SUCCEED (1) #define HELPMSG "help - Show help menu \r\n" \ "getsysinfo - Get system information \r\n" \ "open - Open the CD-ROM \r\n" \ "close - Close the CD-ROM \r\n" \ "swap - Swap mouse button \r\n" \ "restore - Restore mouse button \r\n" \ "exit - Quit Shell" //分发命令 LONG dispath(SOCKET sock, char *pCmd); //存储系统信息的结构体 typedef struct _SYS_INFO { char m_szComputerName[MAXBYTE]; char m_szUserName[MAXBYTE]; OSVERSIONINFO m_sVer; }SYS_INFO, *PSYS_INFO; //获取系统信息 LONG GetSysInfo(SYS_INFO &sysInfo); //打开或关闭光驱 LONG SetCDAudio(bool bOpen); //交换或还原鼠标左右键 void SetMouse(bool bSwap);
control.cpp
//file name: control.cpp #include "control.h" #include <assert.h> LONG dispath( SOCKET sock, char *pCmd ) { LONG lRet = 0; if (NULL == pCmd) { return 0; } if (0 == strcmp(pCmd, "help")) { //发送帮助信息 int nSend = send(sock, HELPMSG, strlen(HELPMSG)+sizeof(char), NULL); if (SOCKET_ERROR != nSend) { lRet = DISPATH_SUCCEED; } } else if (0 == strcmp(pCmd, "getsysinfo")) { //获取系统信息 SYS_INFO sInfo = {0}; sInfo.m_sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (DISPATH_SUCCEED == GetSysInfo(sInfo)) { int nSend = send(sock, (char*)&sInfo, sizeof(SYS_INFO), NULL); if (SOCKET_ERROR != lRet) { lRet = DISPATH_SUCCEED; } } else { int nSend = send(sock, "getsysinfo failed", strlen("open cdaudio door")+sizeof(char), NULL); if (SOCKET_ERROR != nSend) { lRet = DISPATH_SUCCEED; } else { lRet = WSAGetLastError(); } } } else if (0 == strcmp(pCmd, "open")) { //打开光驱 lRet = SetCDAudio(true); int nSend = send(sock, "open cdaudio door", strlen("open cdaudio door")+sizeof(char), NULL); if (SOCKET_ERROR != nSend) { lRet = DISPATH_SUCCEED; } else { lRet = WSAGetLastError(); } } else if (0 == strcmp(pCmd, "close")) { //关闭光驱 lRet = SetCDAudio(false); int nSend = send(sock, "close cdaudio door", strlen("open cdaudio door")+sizeof(char), NULL); if (SOCKET_ERROR != nSend) { lRet = DISPATH_SUCCEED; } else { lRet = WSAGetLastError(); } } else if (0 == strcmp(pCmd, "swap")) { //交换鼠标左右键 SetMouse(true); lRet = DISPATH_SUCCEED; int nSend = send(sock, "swap mouse buttons", strlen("open cdaudio door")+sizeof(char), NULL); if (SOCKET_ERROR != nSend) { lRet = DISPATH_SUCCEED; } else { lRet = WSAGetLastError(); } } else if (0 == strcmp(pCmd, "restore")) { //恢复鼠标左右键 SetMouse(false); lRet = DISPATH_SUCCEED; int nSend = send(sock, "restore mouse buttons", strlen("open cdaudio door")+sizeof(char), NULL); if (SOCKET_ERROR != nSend) { lRet = DISPATH_SUCCEED; } else { lRet = WSAGetLastError(); } } else { //错误的命令 int nSend = send(sock, "Error Commond line", sizeof(char)+strlen("Error Commond line"), NULL); if (SOCKET_ERROR != lRet) { lRet = DISPATH_SUCCEED; } } return lRet; } LONG GetSysInfo( SYS_INFO &sysInfo ) { LONG lRet = DISPATH_SUCCEED; lRet = GetVersionEx(&sysInfo.m_sVer); if (!lRet) { return GetLastError(); } DWORD dwSize = MAXBYTE; lRet = GetComputerName(sysInfo.m_szComputerName, &dwSize); if (!lRet) { return GetLastError(); } dwSize = MAXBYTE; lRet = GetUserName(sysInfo.m_szUserName, &dwSize); if (!lRet) { DWORD dwErr; dwErr = GetLastError(); return dwErr; } return lRet; } LONG SetCDAudio( bool bOpen ) { LONG lRet = 0; if (bOpen) { lRet = mciSendString("set cdaudio door open", NULL, NULL, NULL); } else { lRet = mciSendString("set cdaudio door close", NULL, NULL, NULL); } if (0 != lRet) { return lRet; } return DISPATH_SUCCEED; } void SetMouse( bool bSwap ) { SwapMouseButton(bSwap); }
main.cpp
//file name: main.cpp #include <iostream> #include <WinSock2.h> #include "control.h" #pragma comment(lib, "ws2_32") using namespace std; int main(int argc, char *argv[]) { WSADATA wsaData; SOCKET s; SOCKET clientSocket; if (0 != WSAStartup(MAKEWORD(2,2), &wsaData)) { cout<<"初始化ws2_32.dll失败,错误号为: "<<WSAGetLastError()<<endl; return 0; } //创建套接字 s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == s) { cout<<"创建套接字时发生错误,错误号为: "<<WSAGetLastError()<<endl; goto ERR0; } sockaddr_in sockAddr; sockAddr.sin_family = PF_INET; sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); sockAddr.sin_port = htons(827); //绑定套接字 if(SOCKET_ERROR == bind(s, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR))) { cout<<"绑定套接字时发生错误,错误号为: "<<WSAGetLastError()<<endl; goto ERR1; } //进行监听 if (SOCKET_ERROR == listen(s, 1)) { cout<<"创建监听时发生错误,错误号为: "<<WSAGetLastError()<<endl; goto ERR1; } //创建用来向客服端发送数据的套接字 SOCKADDR ClientAddr; int nSize = sizeof(SOCKADDR); clientSocket = accept(s, (SOCKADDR*)&ClientAddr, &nSize); if (INVALID_SOCKET == clientSocket) { cout<<"创建套接字时发生错误,错误号为: "<<WSAGetLastError()<<endl; goto ERR1; } int nSend = 0; int nRecv = 0; //循环发送消息给客服端,并且对客服端发来的信息进行分发 char szRecv[MAXBYTE] = {0}; while (true) { //发送数据 nSend = send(clientSocket, "Shell>> ", strlen("Shell>> ")+sizeof(char), NULL); if (SOCKET_ERROR == nSend) { cout<<"发送数据时发生错误,错误号为: "<<WSAGetLastError()<<endl; goto ERR; } //接收客服端数据 memset(szRecv, 0, MAXBYTE); nRecv = recv(clientSocket, szRecv, MAXBYTE, NULL); if (0 == nRecv) { cout<<"连接已经被断开"<<endl; goto ERR; } if (SOCKET_ERROR == nRecv) { cout<<"接收数据时发生错误,错误号为: "<<WSAGetLastError()<<endl; goto ERR; } if (0 == strcmp(szRecv, "exit")) { break; } LONG lRet = dispath(clientSocket, szRecv); if (DISPATH_SUCCEED != lRet) { cout<<"分发的命令处理失败, 错误号为: "<<lRet<<endl; goto ERR; } } ERR: closesocket(clientSocket); ERR1: closesocket(s); ERR0: WSACleanup(); return 0; }
不知道为什么接收到的结构体,会有乱码,懂不起鸟,只能慢慢Debug了。我是用的vs2005,在朋友vc6下面就没有乱码,不明白呀。
明白了,竟然是很2的编码问题,服务器端没有选择Unicode字符集,服务器端却选了,然后用了一个char数组去存收到的Unicode字符串。