1. 程式人生 > >小練習:用socket實現Linux和Windows之間的通信

小練習:用socket實現Linux和Windows之間的通信

ren argc 漏洞 markdown tex sockets acc sas -m

在日常生活中,絕大部分人使用的機器通常是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 10

int 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之間的通信