为方便学习,本例没有采用MFC,直接使用Win32 API编程,GCC 4.5.2编译通过。
源代码参见附件。
- /****************************************
- * author : Dante Lee
- * email : bhlzlx@gmail.com
- ****************************************/
- #include <windows.h>
- #include <commctrl.h>
- #include <stdio.h>
- #include <winsock2.h>
- #include <string>
- #include <map>
- #include <algorithm>
- #include "resource.h"
- #define RECV_MSG_FROM_CLIENT WM_USER+1
- #define RECV_MSG_FROM_SERVER WM_USER+2
- #define ERROR_CONNECT_TO_SERVER WM_USER+3
- #define MSG_NEW_CLIENT_CONNECTED WM_USER+4
- #define MSG_CLIENT_DISCONNECTED WM_USER+5
- #pragma push
- #pragma pack(0)
- struct DataPack
- {
- unsigned int cbSize;
- char pData[];
- };
- #pragma pop
- enum RollType
- {
- TypeNone = -1,
- TypeServer,
- TypeClient
- } roll = TypeNone;
- LPCSTR SERVER_IP = "127.0.0.1";
- UINT SERVER_PORT = 4001;
- CHAR MSG_BUFFER[1024];
- CHAR SERVER_IP_BUFFER[32];
- void UINT2IP(char * buffer,UINT ip);
- SOCKET servSock;
- std::map<UINT,SOCKET> clientsSock;
- SOCKET clieSock;
- sockaddr_in addrIn;
- WSAData wsaData;
- WORD wVersionRequested = MAKEWORD(2,1);
- INT error;
- INT addr_in_size = sizeof(sockaddr_in);
- HINSTANCE hInst;
- HWND hMainWnd;
- BOOL StartupServerSock();
- BOOL StartupClientSock();
- DWORD WINAPI ServerThreadProc(LPVOID lpParam);
- DWORD WINAPI ClientThreadProc(LPVOID lpParam);
- BOOL StartupServerSock()
- {
- // Start up
- error = WSAStartup(wVersionRequested,&wsaData);
- if(error == SOCKET_ERROR)
- {
- return FALSE;
- }
- // Bind
- servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- addrIn.sin_addr.s_addr = htonl(INADDR_ANY);
- addrIn.sin_family = AF_INET;
- addrIn.sin_port = SERVER_PORT;
- error = bind(servSock,(sockaddr*)&addrIn,addr_in_size);
- if(error == SOCKET_ERROR)
- {
- printf("Error occurred dureing the binding process...\n ");
- return FALSE;
- }
- // Listen
- error = listen(servSock,2);
- if(error == SOCKET_ERROR)
- {
- return FALSE;
- }
- DWORD newThreadID;
- ::CreateThread(NULL,0,&ServerThreadProc,NULL,0,&newThreadID);
- printf("Start server successfully!\n");
- return TRUE;
- }
- BOOL StartupClientSock()
- {
- // Start up
- error = WSAStartup(wVersionRequested,&wsaData);
- if(error == SOCKET_ERROR)
- {
- return FALSE;
- }
- clieSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- addrIn.sin_addr.s_addr = inet_addr(SERVER_IP_BUFFER);
- addrIn.sin_family = AF_INET;
- addrIn.sin_port = SERVER_PORT;
- DWORD newThreadID;
- ::CreateThread(NULL,0,&ClientThreadProc,NULL,0,&newThreadID);
- printf("Start client sockets successfully!\n");
- return TRUE;
- }
- DWORD WINAPI ClientThreadProc(LPVOID lpParam)
- {
- error = connect(clieSock,(sockaddr *)&addrIn,addr_in_size);
- printf("%d\n,error code: %d",error,WSAGetLastError());
- if(error == SOCKET_ERROR)
- {
- printf("can not connect to server \"%s\"\n",SERVER_IP);
- ::SendMessage(hMainWnd,ERROR_CONNECT_TO_SERVER,0,0);
- }
- else
- {
- // reciever data from server...
- printf("connected successfully!");
- while(TRUE)
- {
- memset(MSG_BUFFER,0,sizeof(MSG_BUFFER));
- int len = recv(clieSock,MSG_BUFFER,sizeof(MSG_BUFFER),0);
- if(len != 0)
- {
- if(len == SOCKET_ERROR)
- {
- strcpy(MSG_BUFFER,"Server was shut down!");
- SendMessage(hMainWnd,RECV_MSG_FROM_SERVER,0,0);
- closesocket(clieSock);
- break;
- }
- printf("recv : %s\n",MSG_BUFFER);
- SendMessage(hMainWnd,RECV_MSG_FROM_SERVER,0,0);
- }
- else
- {
- closesocket(clieSock);
- break;
- }
- }
- }
- return 0;
- }
- DWORD WINAPI ServerThreadProc(LPVOID lpParam)
- {
- SOCKET clientSock = accept(servSock,(sockaddr*)&addrIn,&addr_in_size);
- 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;
- clientsSock[clientIP] = clientSock;
- DWORD newThreadID;
- ::CreateThread(NULL,0,&ServerThreadProc,NULL,0,&newThreadID);
- ::SendMessage(hMainWnd,MSG_NEW_CLIENT_CONNECTED,clientIP,0);
- // Receive Loop
- while(TRUE)
- {
- memset(MSG_BUFFER,0,sizeof(MSG_BUFFER));
- int buffLen = recv(clientSock,MSG_BUFFER,sizeof(MSG_BUFFER)-1,0);
- if(buffLen > 0) // 处理信息
- {
- printf("recv msg : %s\n",MSG_BUFFER);
- SendMessage(hMainWnd,RECV_MSG_FROM_CLIENT,clientIP,0);
- }
- else if(buffLen == 0) // 网络中断
- {
- 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);
- // remove the disconnected client's information from clientsSock
- SendMessage(hMainWnd,MSG_CLIENT_DISCONNECTED,clientIP,0);
- }
- else if(buffLen == SOCKET_ERROR) // 处理错误
- {
- int lastError = WSAGetLastError();
- if (lastError == 10054)
- {
- printf("socket error!\n,error code : %d \n",lastError);
- SendMessage(hMainWnd,MSG_CLIENT_DISCONNECTED,clientIP,0);
- break;
- }
- }
- }
- if(clientsSock.empty())
- {
- shutdown(servSock,1);
- }
- return 0;
- }
- BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- switch(uMsg)
- {
- case RECV_MSG_FROM_CLIENT:
- {
- char temp[1024] = {0};
- ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023);
- std::string msg_main_str = std::string(temp);
- char msgRecv[128];
- char szAddrIP[16];
- UINT2IP(szAddrIP,wParam);
- sprintf(msgRecv,"%s : %s\r\n",szAddrIP,MSG_BUFFER);
- msg_main_str+=msgRecv;
- ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str());
- return TRUE;
- }
- case RECV_MSG_FROM_SERVER:
- {
- char temp[1024] = {0};
- ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023);
- std::string msg_main_str = std::string(temp);
- char msgRecv[128];
- sprintf(msgRecv,"server : %s\r\n",MSG_BUFFER);
- msg_main_str+=msgRecv;
- ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str());
- return TRUE;
- }
- case MSG_NEW_CLIENT_CONNECTED:
- {
- char temp[1024] = {0};
- ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023);
- std::string msg_main_str = std::string(temp);
- char msgRecv[128];
- char szAddrIP[16];
- UINT2IP(szAddrIP,wParam);
- sprintf(msgRecv,"client %s connected...\r\n",szAddrIP);
- msg_main_str+=msgRecv;
- ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str());
- return TRUE;
- }
- case MSG_CLIENT_DISCONNECTED:
- {
- char temp[1024] = {0};
- ::GetDlgItemText(hMainWnd,IDC_MSG_MAIN,temp,1023);
- std::string msg_main_str = std::string(temp);
- char msgRecv[128];
- char szAddrIP[16];
- UINT2IP(szAddrIP,wParam);
- sprintf(msgRecv,"client %s disconnected...\r\n",szAddrIP);
- clientsSock.erase(wParam);
- printf("clients left : %d \n",clientsSock.size());
- msg_main_str+=msgRecv;
- ::SetDlgItemText(hMainWnd,IDC_MSG_MAIN,msg_main_str.c_str());
- return TRUE;
- }
- case WM_INITDIALOG:
- {
- hMainWnd = hwndDlg;
- }
- return TRUE;
- case WM_CLOSE:
- {
- EndDialog(hwndDlg, 0);
- }
- return TRUE;
- case ERROR_CONNECT_TO_SERVER:
- {
- ::MessageBox(NULL,"Can not connect to the specified IP address!","Error!",MB_OK);
- ::EnableWindow(::GetDlgItem(hMainWnd,IDC_CONNECT),TRUE);
- return TRUE;
- }
- case WM_COMMAND:
- {
- switch(LOWORD(wParam))
- {
- case IDC_SEND:
- {
- if(roll == TypeNone)
- {
- ::MessageBox(hMainWnd,"Socket not initialized yet!","Error!",MB_OK);
- return TRUE;
- }
- HWND hWndSend = ::GetDlgItem(hMainWnd,IDC_MSG_SEND);
- CHAR Buffer[1024];
- ::GetWindowText(hWndSend,Buffer,1023);
- ::SetWindowText(::GetDlgItem(hMainWnd,IDC_MSG_SEND),"");
- switch(roll)
- {
- case TypeServer:
- {
- //send to all client;
- std::map<UINT,SOCKET>::iterator iter = clientsSock.begin();
- std::map<UINT,SOCKET>::iterator iterEnd = clientsSock.end();
- while(iter != iterEnd)
- {
- send(iter->second,Buffer,strlen(Buffer) + 1,SOCK_STREAM);
- iter++;
- }
- break;
- }
- case TypeClient:
- {
- //send to server
- send(clieSock,Buffer,strlen(Buffer) + 1,SOCK_STREAM);
- break;
- }
- case TypeNone:
- break;
- }
- break;
- }
- case IDC_STARTSERV:
- {
- BOOL ret = StartupServerSock();
- if(ret)
- {
- roll = TypeServer;
- ::EnableWindow(::GetDlgItem(hMainWnd,IDC_STARTSERV),FALSE);
- ::EnableWindow(::GetDlgItem(hMainWnd,IDC_CONNECT),FALSE);
- }
- break;
- }
- case IDC_CONNECT:
- {
- HWND hWndIP = ::GetDlgItem(hMainWnd,IDC_IPADDRESS);
- ::GetWindowText(hWndIP,SERVER_IP_BUFFER,sizeof(SERVER_IP_BUFFER));
- if(strcmp(SERVER_IP_BUFFER,"0.0.0.0") == 0)
- {
- ::SetWindowText(hWndIP,"127.0.0.1");
- strcpy(SERVER_IP_BUFFER,"127.0.0.1");
- }
- BOOL ret = StartupClientSock();
- if(ret)
- {
- roll = TypeClient;
- ::EnableWindow(::GetDlgItem(hMainWnd,IDC_CONNECT),FALSE);
- }
- else
- {
- ::MessageBox(NULL,"Can not start client socket!","Error!",MB_OK);
- }
- break;
- }
- }
- }
- return TRUE;
- }
- return FALSE;
- }
- void UINT2IP(char * buffer,UINT ip)
- {
- sprintf(buffer,"%d.%d.%d.%d",ip>>24,ip>>16&0xff,ip>>8&0xff,ip&0xff);
- }
- int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
- {
- hInst=hInstance;
- InitCommonControls();
- return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
- }