Windows(受信)からUbuntsu(サーバ)へ接続しバイナリデータ受信

## 目的
WindowsからUbuntsuへ接続しバイナリデータを受信する実験をしました。
２台をネットに繋がっていないポケットWIFIへ接続します。
ネットに繋げず完全に外界から隔絶された環境を作ります。
Ubuntsu側8080ポートで接続を受け付けます。
WindowsからIPアドレスを指定してUbuntuへ接続しバイナリデータを受信します。

## 実験風景
![IMG_2006.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/91a29061-4717-4a5f-96d3-4b810b8fa04c.jpeg)
![uploading...0]()

何度上げても失敗するのでこのままにしておいて後日あげます。

## ネットの接続状態
### 使用したポケットWIFI
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/e71a8a6a-6c0a-4d0e-b124-8264b91b0601.png)
### ２台ともポケットWIFIへ接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/4b70fb4b-96f0-43c9-bd24-934b5973160f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/4ef9bf0f-688e-42f6-a63b-57fc12ebe983.png)

### サーバ側UbuntuのIPアドレス
下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/231493d9-1a89-4419-aa13-f14e11fe92b9.png)

## 通信開始
### Ubuntu接続受付
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/eaf0e52f-c99c-44cf-b6d5-3fdf5843edb5.png)

### Windowsから接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/5dce6d76-c499-4fa3-aee2-82b70196f7bd.png)

### 送信完了後Ubuntu
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/a2354116-df32-4924-b704-41f74b65a403.png)

## 検証プログラム
```client.c
/*
 * 【Windows受信クライアント】バイナリデータ受信プログラム
 * コンパイル: gcc client.c -o client.exe -lws2_32
 */

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <stdint.h>

#pragma comment(lib, "ws2_32.lib")

/* 全データ受信関数 */
int recv_all(SOCKET sock, void *buffer, size_t length) {
    size_t total = 0;
    char *buf = (char*)buffer;
    while (total < length) {
        int received = recv(sock, buf + total, length - total, 0);
        if (received <= 0) return -1;
        total += received;
    }
    return 0;
}

int main() {
    WSADATA wsa;
    SOCKET sock;
    struct sockaddr_in server_addr;

    /* Winsock初期化 */
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
        printf("WSAStartup failed: %d\n", WSAGetLastError());
        return 1;
    }

    /* ソケット作成 */
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
        printf("Socket creation failed: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    /* サーバー設定（UbuntuのIPを指定） */
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = inet_addr("192.168.0.101"); // UbuntuのIPに変更

    /* サーバー接続 */
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
        printf("Connection failed: %d\n", WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    printf("Connected to server\n");

    /* データサイズ受信 */
    uint32_t data_size;
    if (recv_all(sock, &data_size, sizeof(data_size)) < 0) {
        printf("Size reception failed\n");
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    /* エンディアン変換 */
    data_size = ntohl(data_size);
    printf("Expected data size: %u bytes\n", data_size);

    /* データ受信 */
    char *buffer = malloc(data_size);
    if (!buffer) {
        printf("Memory allocation failed\n");
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    if (recv_all(sock, buffer, data_size) < 0) {
        printf("Data reception failed\n");
        free(buffer);
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    printf("Reception successful! Data content:\n");
    for (uint32_t i = 0; i < data_size; i++) {
        printf("%02X ", (unsigned char)buffer[i]);
    }
    printf("\n");

    /* 後処理 */
    free(buffer);
    closesocket(sock);
    WSACleanup();
    return 0;
}
```

```server.c
/*
 * 【Ubuntu送信サーバー】バイナリデータ送信プログラム
 * コンパイル: gcc server.c -o server
 * 実行: ./server
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

/* 全データ送信関数 */
int send_all(int sock, const void *buffer, size_t length) {
    size_t total = 0;
    const char *buf = (const char*)buffer;
    while (total < length) {
        ssize_t sent = send(sock, buf + total, length - total, 0);
        if (sent <= 0) return -1;
        total += sent;
    }
    return 0;
}

int main() {
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);

    /* ソケット作成 */
    server_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock < 0) {
        perror("ソケット作成失敗");
        exit(EXIT_FAILURE);
    }

    /* サーバー設定 */
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    /* バインド */
    if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("バインド失敗");
        close(server_sock);
        exit(EXIT_FAILURE);
    }

    /* 接続待機 */
    if (listen(server_sock, 1) < 0) {
        perror("待機失敗");
        close(server_sock);
        exit(EXIT_FAILURE);
    }

    printf("8080ポートで待機中...\n");

    /* クライアント接続受付 */
    client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &addr_len);
    if (client_sock < 0) {
        perror("接続受付失敗");
        close(server_sock);
        exit(EXIT_FAILURE);
    }

    printf("クライアント接続: %s:%d\n", 
           inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

    /* 送信データ準備 */
    const char data[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21}; // "Hello!"
    uint32_t data_size = sizeof(data);
    uint32_t net_size = htonl(data_size);

    /* データサイズ送信 */
    if (send_all(client_sock, &net_size, sizeof(net_size)) < 0) {
        perror("サイズ送信失敗");
        close(client_sock);
        close(server_sock);
        exit(EXIT_FAILURE);
    }

    /* バイナリデータ送信 */
    if (send_all(client_sock, data, data_size) < 0) {
        perror("データ送信失敗");
        close(client_sock);
        close(server_sock);
        exit(EXIT_FAILURE);
    }

    printf("%d バイト送信成功\n", data_size);

    /* 後処理 */
    close(client_sock);
    close(server_sock);
    return 0;
}
```