Win32 Socket 通讯 WinSock 编程示例 更新

为方便学习,本例没有采用MFC,直接使用Win32 API编程,GCC 4.5.2编译经过。编程

源代码参见附件。windows

 

 

  
  
  
  
  1. /**************************************** 
  2.  *    author : Dante Lee 
  3.  *    email  : bhlzlx@gmail.com 
  4. ****************************************/ 
  5.  
  6. #include <windows.h> 
  7. #include <commctrl.h> 
  8. #include <stdio.h> 
  9. #include <winsock2.h> 
  10. #include <string> 
  11. #include <map> 
  12. #include <algorithm> 
  13.  
  14. #include "resource.h" 
  15.  
  16. #define RECV_MSG_FROM_CLIENT WM_USER+1 
  17. #define RECV_MSG_FROM_SERVER WM_USER+2 
  18. #define ERROR_CONNECT_TO_SERVER WM_USER+3 
  19. #define MSG_NEW_CLIENT_CONNECTED WM_USER+4 
  20. #define MSG_CLIENT_DISCONNECTED WM_USER+5 
  21.  
  22. #pragma push 
  23. #pragma pack(0) 
  24. struct DataPack 
  25.     unsigned int cbSize; 
  26.     char pData[]; 
  27. }; 
  28. #pragma pop 
  29.  
  30. enum RollType 
  31.     TypeNone   = -1, 
  32.     TypeServer, 
  33.     TypeClient 
  34. } roll = TypeNone; 
  35.  
  36. LPCSTR SERVER_IP    = "127.0.0.1"
  37. UINT   SERVER_PORT  = 4001; 
  38. CHAR   MSG_BUFFER[1024]; 
  39. CHAR   SERVER_IP_BUFFER[32]; 
  40.  
  41. void UINT2IP(char * buffer,UINT ip); 
  42.  
  43. SOCKET servSock; 
  44. std::map<UINT,SOCKET> clientsSock; 
  45. SOCKET clieSock; 
  46. sockaddr_in addrIn; 
  47. WSAData wsaData; 
  48. WORD    wVersionRequested = MAKEWORD(2,1); 
  49. INT     error; 
  50.  
  51. INT addr_in_size = sizeof(sockaddr_in); 
  52.  
  53. HINSTANCE hInst; 
  54. HWND      hMainWnd; 
  55.  
  56. BOOL StartupServerSock(); 
  57. BOOL StartupClientSock(); 
  58. DWORD WINAPI ServerThreadProc(LPVOID lpParam); 
  59. DWORD WINAPI ClientThreadProc(LPVOID lpParam); 
  60.  
  61. BOOL StartupServerSock() 
  62.     // Start up 
  63.     error = WSAStartup(wVersionRequested,&wsaData); 
  64.     if(error == SOCKET_ERROR) 
  65.     { 
  66.         return FALSE; 
  67.     } 
  68.     // Bind 
  69.     servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
  70.     addrIn.sin_addr.s_addr =  htonl(INADDR_ANY); 
  71.     addrIn.sin_family = AF_INET; 
  72.     addrIn.sin_port = SERVER_PORT; 
  73.     error = bind(servSock,(sockaddr*)&addrIn,addr_in_size); 
  74.     if(error == SOCKET_ERROR) 
  75.     { 
  76.         printf("Error occurred dureing the binding process...\n "); 
  77.         return FALSE; 
  78.     } 
  79.     // Listen 
  80.     error = listen(servSock,2); 
  81.     if(error == SOCKET_ERROR) 
  82.     { 
  83.         return FALSE; 
  84.     } 
  85.     DWORD newThreadID; 
  86.     ::CreateThread(NULL,0,&ServerThreadProc,NULL,0,&newThreadID); 
  87.     printf("Start server successfully!\n"); 
  88.     return TRUE; 
  89.  
  90. BOOL StartupClientSock() 
  91.     // Start up 
  92.     error = WSAStartup(wVersionRequested,&wsaData); 
  93.     if(error == SOCKET_ERROR) 
  94.     { 
  95.         return FALSE; 
  96.     } 
  97.     clieSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
  98.     addrIn.sin_addr.s_addr =  inet_addr(SERVER_IP_BUFFER); 
  99.     addrIn.sin_family = AF_INET; 
  100.     addrIn.sin_port = SERVER_PORT; 
  101.     DWORD newThreadID; 
  102.     ::CreateThread(NULL,0,&ClientThreadProc,NULL,0,&newThreadID); 
  103.     printf("Start client sockets successfully!\n"); 
  104.     return TRUE; 
  105.  
  106. DWORD WINAPI ClientThreadProc(LPVOID lpParam) 
  107.     error = connect(clieSock,(sockaddr *)&addrIn,addr_in_size); 
  108.     printf("%d\n,error code: %d",error,WSAGetLastError()); 
  109.     if(error == SOCKET_ERROR) 
  110.     { 
  111.         printf("can not connect to server \"%s\"\n",SERVER_IP); 
  112.         ::SendMessage(hMainWnd,ERROR_CONNECT_TO_SERVER,0,0); 
  113.     } 
  114.     else 
  115.     { 
  116.         // reciever data from server... 
  117.         printf("connected successfully!"); 
  118.         while(TRUE) 
  119.         { 
  120.             memset(MSG_BUFFER,0,sizeof(MSG_BUFFER)); 
  121.             int len = recv(clieSock,MSG_BUFFER,sizeof(MSG_BUFFER),0); 
  122.             if(len != 0) 
  123.             { 
  124.                 if(len == SOCKET_ERROR) 
  125.                 { 
  126.                     strcpy(MSG_BUFFER,"Server was shut down!"); 
  127.                     SendMessage(hMainWnd,RECV_MSG_FROM_SERVER,0,0); 
  128.                     closesocket(clieSock); 
  129.                     break
  130.                 } 
  131.                 printf("recv : %s\n",MSG_BUFFER); 
  132.                 SendMessage(hMainWnd,RECV_MSG_FROM_SERVER,0,0); 
  133.             } 
  134.             else 
  135.             { 
  136.                 closesocket(clieSock); 
  137.                 break
  138.             } 
  139.         } 
  140.     } 
  141.     return 0; 
  142.  
  143. DWORD WINAPI ServerThreadProc(LPVOID lpParam) 
  144.     SOCKET clientSock = accept(servSock,(sockaddr*)&addrIn,&addr_in_size); 
  145.     UINT clientIP = addrIn.sin_addr.s_net<<24|addrIn.sin_addr.s_host<<16|addrIn.sin_addr.s_lh<<8|addrIn.sin_addr.s_impno; 
  146.     clientsSock[clientIP] = clientSock; 
  147.     DWORD newThreadID; 
  148.     ::CreateThread(NULL,0,&ServerThreadProc,NULL,0,&newThreadID); 
  149.     ::SendMessage(hMainWnd,MSG_NEW_CLIENT_CONNECTED,clientIP,0); 
  150.     // Receive Loop 
  151.     while(TRUE) 
  152.     { 
  153.         memset(MSG_BUFFER,0,sizeof(MSG_BUFFER)); 
  154.         int buffLen = recv(clientSock,MSG_BUFFER,sizeof(MSG_BUFFER)-1,0); 
  155.         if(buffLen > 0)         // 处理信息 
  156.         { 
  157.             printf("recv msg : %s\n",MSG_BUFFER); 
  158.             SendMessage(hMainWnd,RECV_MSG_FROM_CLIENT,clientIP,0); 
  159.         } 
  160.         else if(buffLen == 0) // 网络中断 
  161.         { 
  162.             printf("connection -> ip : %d.%d.%d.%d failed.\n",addrIn.sin_addr.s_net,addrIn.sin_addr.s_host,addrIn.sin_addr.s_lh,addrIn.sin_addr.s_impno); 
  163.             // remove the disconnected client's information from clientsSock 
  164.             SendMessage(hMainWnd,MSG_CLIENT_DISCONNECTED,clientIP,0); 
  165.  
  166.         } 
  167.         else if(buffLen == SOCKET_ERROR) // 处理错误 
  168.         { 
  169.             int lastError = WSAGetLastError(); 
  170.             if (lastError == 10054) 
  171.             { 
  172.                 printf("socket error!\n,error code : %d \n",lastError); 
  173.                 SendMessage(hMainWnd,MSG_CLIENT_DISCONNECTED,clientIP,0); 
  174.                 break
  175.             } 
  176.         } 
  177.     } 
  178.  
  179.     if(clientsSock.empty()) 
  180.     { 
  181.         shutdown(servSock,1); 
  182.     } 
  183.     return 0; 
  184.  
  185. BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 
  186.     switch(uMsg) 
  187.     { 
  188.     case RECV_MSG_FROM_CLIENT: 
  189.         { 
  190.             char temp[1024] = {0}; 
  191.             ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023); 
  192.             std::string msg_main_str = std::string(temp); 
  193.             char msgRecv[128]; 
  194.             char szAddrIP[16]; 
  195.             UINT2IP(szAddrIP,wParam); 
  196.             sprintf(msgRecv,"%s : %s\r\n",szAddrIP,MSG_BUFFER); 
  197.             msg_main_str+=msgRecv; 
  198.             ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str()); 
  199.             return TRUE; 
  200.         } 
  201.     case RECV_MSG_FROM_SERVER: 
  202.         { 
  203.             char temp[1024] = {0}; 
  204.             ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023); 
  205.             std::string msg_main_str = std::string(temp); 
  206.             char msgRecv[128]; 
  207.             sprintf(msgRecv,"server : %s\r\n",MSG_BUFFER); 
  208.             msg_main_str+=msgRecv; 
  209.             ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str()); 
  210.             return TRUE; 
  211.         } 
  212.     case MSG_NEW_CLIENT_CONNECTED: 
  213.         { 
  214.             char temp[1024] = {0}; 
  215.             ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023); 
  216.             std::string msg_main_str = std::string(temp); 
  217.             char msgRecv[128]; 
  218.             char szAddrIP[16]; 
  219.             UINT2IP(szAddrIP,wParam); 
  220.             sprintf(msgRecv,"client %s connected...\r\n",szAddrIP); 
  221.             msg_main_str+=msgRecv; 
  222.             ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str()); 
  223.             return TRUE; 
  224.         } 
  225.     case MSG_CLIENT_DISCONNECTED: 
  226.         { 
  227.             char temp[1024] = {0}; 
  228.             ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023); 
  229.             std::string msg_main_str = std::string(temp); 
  230.             char msgRecv[128]; 
  231.             char szAddrIP[16]; 
  232.             UINT2IP(szAddrIP,wParam); 
  233.             sprintf(msgRecv,"client %s disconnected...\r\n",szAddrIP); 
  234.             clientsSock.erase(wParam); 
  235.             printf("clients left : %d \n",clientsSock.size()); 
  236.             msg_main_str+=msgRecv; 
  237.             ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str()); 
  238.             return TRUE; 
  239.         } 
  240.     case WM_INITDIALOG: 
  241.         { 
  242.             hMainWnd = hwndDlg; 
  243.         } 
  244.     return TRUE; 
  245.  
  246.     case WM_CLOSE: 
  247.         { 
  248.             EndDialog(hwndDlg, 0); 
  249.         } 
  250.     return TRUE; 
  251.     case ERROR_CONNECT_TO_SERVER: 
  252.         { 
  253.             ::MessageBox(NULL,"Can not connect to the specified IP address!","Error!",MB_OK); 
  254.             ::EnableWindow(::GetDlgItem(hMainWnd,IDC_CONNECT),TRUE); 
  255.             return TRUE; 
  256.         } 
  257.  
  258.     case WM_COMMAND: 
  259.     { 
  260.         switch(LOWORD(wParam)) 
  261.         { 
  262.             case IDC_SEND: 
  263.             { 
  264.                 if(roll == TypeNone) 
  265.                 { 
  266.                     ::MessageBox(hMainWnd,"Socket not initialized yet!","Error!",MB_OK); 
  267.                     return TRUE; 
  268.                 } 
  269.                 HWND hWndSend = ::GetDlgItem(hMainWnd,IDC_MSG_SEND); 
  270.                 CHAR Buffer[1024]; 
  271.                 ::GetWindowText(hWndSend,Buffer,1023); 
  272.                 ::SetWindowText(::GetDlgItem(hMainWnd,IDC_MSG_SEND),""); 
  273.                 switch(roll) 
  274.                 { 
  275.                 case TypeServer: 
  276.                     { 
  277.                         //send to all client; 
  278.                         std::map<UINT,SOCKET>::iterator iter = clientsSock.begin(); 
  279.                         std::map<UINT,SOCKET>::iterator iterEnd = clientsSock.end(); 
  280.                         while(iter != iterEnd) 
  281.                         { 
  282.                             send(iter->second,Buffer,strlen(Buffer) + 1,SOCK_STREAM); 
  283.                             iter++; 
  284.                         } 
  285.                         break
  286.                     } 
  287.                 case TypeClient: 
  288.                     { 
  289.                         //send to server 
  290.                         send(clieSock,Buffer,strlen(Buffer) + 1,SOCK_STREAM); 
  291.                         break
  292.                     } 
  293.                 case TypeNone: 
  294.                     break
  295.                 } 
  296.                 break
  297.             } 
  298.             case IDC_STARTSERV: 
  299.             { 
  300.                 BOOL ret = StartupServerSock(); 
  301.                 if(ret) 
  302.                 { 
  303.                     roll = TypeServer; 
  304.                     ::EnableWindow(::GetDlgItem(hMainWnd,IDC_STARTSERV),FALSE); 
  305.                     ::EnableWindow(::GetDlgItem(hMainWnd,IDC_CONNECT),FALSE); 
  306.                 } 
  307.  
  308.                 break
  309.             } 
  310.             case IDC_CONNECT: 
  311.             { 
  312.                 HWND hWndIP = ::GetDlgItem(hMainWnd,IDC_IPADDRESS); 
  313.                 ::GetWindowText(hWndIP,SERVER_IP_BUFFER,sizeof(SERVER_IP_BUFFER)); 
  314.                 if(strcmp(SERVER_IP_BUFFER,"0.0.0.0") == 0) 
  315.                 { 
  316.                     ::SetWindowText(hWndIP,"127.0.0.1"); 
  317.                     strcpy(SERVER_IP_BUFFER,"127.0.0.1"); 
  318.                 } 
  319.                 BOOL ret = StartupClientSock(); 
  320.                 if(ret) 
  321.                 { 
  322.                     roll = TypeClient; 
  323.                     ::EnableWindow(::GetDlgItem(hMainWnd,IDC_CONNECT),FALSE); 
  324.                 } 
  325.                 else 
  326.                 { 
  327.                     ::MessageBox(NULL,"Can not start client socket!","Error!",MB_OK); 
  328.                 } 
  329.  
  330.                 break
  331.             } 
  332.  
  333.  
  334.         } 
  335.     } 
  336.     return TRUE; 
  337.     } 
  338.     return FALSE; 
  339.  
  340. void UINT2IP(char * buffer,UINT ip) 
  341.     sprintf(buffer,"%d.%d.%d.%d",ip>>24,ip>>16&0xff,ip>>8&0xff,ip&0xff); 
  342.  
  343.  
  344. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 
  345.     hInst=hInstance; 
  346.     InitCommonControls(); 
  347.     return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);