C++tcp伺服器和跨平臺客戶端
阿新 • • 發佈:2020-07-08
TcpServer
#define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <windows.h> #include <winsock2.h> #include <iostream> #include <thread> #include <mutex> #include <chrono> #pragma comment(lib,"ws2_32.lib") std::mutex g_Mutex; bool g_IsQuit = false; void QuitServer() { while (!g_IsQuit) { short key = GetAsyncKeyState('A'); if(key&0x0001) { g_Mutex.lock(); g_IsQuit = true; g_Mutex.unlock(); } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } int main() { //1.初始化網路環境 WORD wVersion = MAKEWORD(2, 2); WSADATA wsaData; int err = WSAStartup(wVersion, &wsaData); if (err != 0) { printf("網路初始化錯誤,錯誤程式碼%d\n", err); system("pause"); return 0; } //2.建立監聽套接字 SOCKET listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if (INVALID_SOCKET == listenSock) { printf("監聽套接字建立失敗\n"); WSACleanup(); system("pause"); return 0; } //3.設定伺服器的埠資訊 sockaddr_in sin; sin.sin_port = htons(6666); sin.sin_family = AF_INET; sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任意ip //4.繫結地址資訊到監聽套接字 if (SOCKET_ERROR == bind(listenSock, (sockaddr*)&sin, sizeof(sin))) { printf("繫結監聽套接字建立失敗\n"); closesocket(listenSock); WSACleanup(); system("pause"); return 0; } //5.開始監聽 if (SOCKET_ERROR == listen(listenSock, 100)) { printf("監聽出現錯誤\n"); closesocket(listenSock); WSACleanup(); system("pause"); return 0; } //6.收發資訊 sockaddr_in clientaddinfo; int addlen = sizeof(clientaddinfo); SOCKET clientsock; clientsock = accept(listenSock, (sockaddr*)&clientaddinfo, &addlen); if (INVALID_SOCKET == clientsock) { printf("Accept錯誤\n"); closesocket(listenSock); WSACleanup(); system("pause"); return 0; } //使用多執行緒轉發和接收資訊 while (!g_IsQuit) { printf("接收到一個客戶:%d,IP:%s,Port:&d\n", clientsock, inet_ntoa(clientaddinfo.sin_addr), clientaddinfo.sin_port); char buf[MAX_PATH] = {}; recv(clientsock, buf, MAX_PATH - 1, 0); printf("接收到的資料:%s\n", buf); send(clientsock, "this is my backdata!", strlen("this is my backdata!") + 1,0); } //7.關閉套接字和網路環境 closesocket(clientsock); closesocket(listenSock); WSACleanup(); system("pause"); return 0; }
Linux跨平臺網路客戶端
#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <windows.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") #else #include <unistd.h> #include <arpa/inet.h> #include <string.h> #define MAX_PATH 260 typedef int SOCKET; #define INVALID_SOCKET (SOCKET)(~0) #define SOCKET_ERROR (-1) #define WSACleanup() // #endif #include <iostream> #include <thread> #include <mutex> #include <chrono> using namespace std; bool g_IsQuit = false; bool g_IsSend = false; char g_SendBuffer[MAX_PATH]; mutex g_Mutex1; mutex g_Mutex2; void InputData() { while (!g_IsQuit ) { printf("input msg:\n"); scanf("%s",g_SendBuffer); if (strcmp(g_SendBuffer,"exit")==0) { g_Mutex1.lock(); g_IsQuit = true; g_Mutex1.unlock(); break; }else if (!g_IsSend) { g_Mutex2.lock(); g_IsSend = true; g_Mutex2.unlock(); } this_thread::sleep_for(chrono::milliseconds(1)); } } int main() { #ifdef _WIN32 WORD wVersion = MAKEWORD(2, 2); WSADATA wsaData; int err = WSAStartup(wVersion, &wsaData); if (err != 0) { printf("初始化錯誤%d\n", err); system("pause"); return 0; } #endif SOCKET clientSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if (INVALID_SOCKET == clientSock) { printf("create clientsocket failed\n"); WSACleanup(); system("pause"); return 0; } sockaddr_in sin; sin.sin_port = htons(12345); sin.sin_family = AF_INET; #ifdef _WIN32 sin.sin_addr.S_un.S_addr = inet_addr("192.168.1.2"); #else sin.sin_addr.s_addr = inet_addr("192.168.1.2"); #endif if (SOCKET_ERROR == connect(clientSock, (sockaddr*)&sin, sizeof(sin))) { printf("錯誤\n"); #ifdef _WIN32 closesocket(clientSock); #else close(clientSock); #endif WSACleanup(); system("pause"); return 0; } thread inputthread(InputData); inputthread.detach(); char recvdata[MAX_PATH] = {}; while (!g_IsQuit) { if (g_IsSend) { printf("start send data\n"); send(clientSock,g_SendBuffer, strlen(g_SendBuffer) + 1, 0); printf("start recv data\n"); recv(clientSock, recvdata, MAX_PATH, 0); printf("reved msg:%s\n", recvdata); g_Mutex2.lock(); g_IsSend = false; g_Mutex2.unlock(); printf("lock end\n"); } this_thread::sleep_for(chrono::milliseconds(1)); } #ifdef _WIN32 closesocket(clientSock); #else close(clientSock); #endif WSACleanup(); return 0; }
總結
- 跨平臺注意編碼
- 通過使用內建的巨集,可以進行作業系統判斷 #ifdef _WIN32 #endif
- arpa/inet.h:IP地址轉換