標籤:bre 位元組順序 img down 客戶 var size 緩衝區 winsock
在日常生活中,絕大部分人使用的機器通常是windows系統,可是對於研發人員,開發、編譯等工作往往是建立在linux機器上。其實。在伺服器方面,Linux、UNIX和WindowsServer佔領了市場的大部分份額;在超級電腦方面,Linux代替Unix成為了第一大作業系統。
通訊是電腦和作業系統的一大任務,通過ftp、ping、ssh等方式。人們能夠非常方便與伺服器串連。一個龐大的網路上的兩個程式通過一個雙向的通訊串連實現資料的交換,這個串連的一端稱為一個socket。
windows系統使用的是windows socket,而linux使用的posix socket。今天結合了網上一些經典常式,寫了一個簡單的socket代碼,實現Ubuntu(虛擬機器中)和Windows的通訊。
Windows平台下用戶端的實現代碼:
#include <stdio.h>#include <Windows.h>#pragma comment(lib, "ws2_32.lib")#define Port 5000#define IP_ADDRESS "172.30.70.95"int main(int argc, char* argv[]) // argc是命令列總的參數個數{ WSADATA s; // 用來儲存調用AfxSocketInit全域函數返回的Windows Sockets初始化資訊 SOCKET ClientSocket; struct sockaddr_in ClientAddr; // 一個sockaddr_in型的結構體對象 int ret = 0; char SendBuffer[MAX_PATH]; // Windows的MAX_PATH預設是260 // 初始化Windows Socket // WSAStartup函數對Winsock服務的初始化 if (WSAStartup(MAKEWORD(2, 2), &s) != 0) // 通過串連兩個給定的無符號參數,首個參數為低位元組 { printf("Init Windows Socket Failed! Error: %d\n", GetLastError()); getchar(); return -1; } while (1) { // 建立一個套介面 // 假設這樣一個套介面用connect()與一個指定連接埠串連 // 則可用send()和recv()與該連接埠進行資料報的發送與接收 // 當會話結束後,調用closesocket() ClientSocket = socket(AF_INET, // 僅僅支援ARPA Internet地址格式 SOCK_STREAM, // 新套介面的類型描寫敘述 IPPROTO_TCP); // 套介面所用的協議 if (ClientSocket == INVALID_SOCKET) { printf("Create Socket Failed! Error: %d\n", GetLastError()); getchar(); return -1; } ClientAddr.sin_family = AF_INET; ClientAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS); // 定義IP地址 ClientAddr.sin_port = htons(Port); // 將主機的無符號短整形數轉換成網路位元組順序 memset(ClientAddr.sin_zero, 0X00, 8); // 函數通常為新申請的記憶體做初始化工作 // 串連Socket ret = connect(ClientSocket, (struct sockaddr*)&ClientAddr, sizeof(ClientAddr)); if (ret == SOCKET_ERROR) { printf("Socket Connect Failed! Error:%d\n", GetLastError()); getchar(); return -1; } else { printf("Socket Connect Succeed!"); } printf("Input Data: "); while (1) { scanf("%s", &SendBuffer); // 發送資料至伺服器 ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), // 返回傳送緩衝區資料長度 0); if (ret == SOCKET_ERROR) { printf("Send Information Failed! Error:%d\n", GetLastError()); getchar(); break; } break; } // 關閉socket closesocket(ClientSocket); if (SendBuffer[0] == ‘q‘) // 設定輸入第一個字元為q時退出 { printf("Quit!\n"); break; } } WSACleanup(); getchar(); return 0;}
我的linux(Ubuntu)端網路資訊:
linux(Ubuntu)平台下的伺服器代碼:
#include <unistd.h>#include <stdio.h>#include <i386-linux-gnu/sys/socket.h>#include <netinet/in.h>#include <i386-linux-gnu/sys/types.h>#include <stdlib.h>#include <string.h>#define SERVER_PORT 5000#define LENGTH_OF_LISTEN_QUEUE 20#define BUFFER_SIZE 10int main() // (int argc, char* argv[]){ struct sockaddr_in server_addr; int server_socket; int opt = 1; bzero(&server_addr, sizeof(server_addr)); // 置位元組字串前n個位元組為0,包含‘\0‘ server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); // 轉小端,INADDR_ANY就是指定地址為0.0.0.0的地址 server_addr.sin_port = htons(SERVER_PORT); // 建立一個Socket server_socket = socket(PF_INET, SOCK_STREAM, 0); if (server_socket < 0) { printf("Create Socket Failed!\n"); exit(1); } // bind a socket setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if(bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr))) { printf("Server Bind Port: %d Failed!\n", SERVER_PORT); exit(1); } // 監聽Socket if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE)) { printf("Server Listen Failed!\n"); exit(1); } while(1) { struct sockaddr_in client_addr; int client_socket; socklen_t length; char Buffer[BUFFER_SIZE]; // 串連用戶端Socket length = sizeof(client_addr); client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length); if (client_socket < 0) { printf("Server Accept Failed!\n"); break; } // 從用戶端接收資料 while(1) { bzero(Buffer, BUFFER_SIZE); length = recv(client_socket, Buffer, BUFFER_SIZE, 0); if (length < 0) { printf("Server Recieve Data Failed!\n"); break; } if (‘q‘ == Buffer[0]) { printf("Quit!\n"); break; } printf("%s\n", Buffer); break; } close(client_socket); } close(server_socket); return 0;}
在開啟用戶端時。伺服器端要確保已處於監聽狀態,否則串連失敗:
開啟伺服器端程式例如以下:
傳輸資料成功:
這個小實驗僅僅花了非常少的時間調試,且僅僅能單向發送資料。功能單一。純粹僅僅是一個小練習。socket編程的調試中,主要關注程式出錯時返回的錯誤值,從中往往能非常快找出代碼的漏洞。
參考連結:http://blog.csdn.net/feixiaoxing/article/details/8567162
小練習:用socket實現Linux和Windows之間的通訊