Home WinSock File Transfer with TCP (Client)
Post
Cancel

WinSock File Transfer with TCP (Client)

TCP 기반의 서버 클라이언트 파일 전송 프로그램 (클라이언트 파트)

타 머신과 테스트 경우 코드상 IP를 해당 머신의 IP로 수정.

받은 파일이 열리지 않은 경우 recv.mp4의 확장자 확인 (서버 측에서 보낼 파일 명을 미리 전송함으로서 개선 가능)

사용 포트 : 9090
기본 IP : localhost

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* Server */ 
/* Client */
#pragma comment (lib,“ws2_32.lib”)
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <Windows.h>
#include <time.h>
#define BUFSIZE 65536
#define PORT 9093
#define IP “127.0.0.1”
char* pbFile2;
void WINAPI dataRecv(LPVOID arg) {
    SOCKET dataSock = (SOCKET)arg;
    SOCKADDR_IN dataAddr;
    int dataAddrSz = sizeof(dataAddr);
    int retval;
    getpeername(dataSock, (SOCKADDR*)&dataAddr, &dataAddrSz);
    do {
        retval = recv(dataSock, pbFile2, BUFSIZE, 0);
        pbFile2 += retval;
        if (retval == 0) break;
        else if (retval == SOCKET_ERROR) break;
    } while (retval > 0);
}
int main() {
    time_t start_time, end_time;
    float gap;
    start_time = clock(); // 시작 시간 측정
    // WinSock 초기화
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) return 1;
    // Socket 생성
    SOCKET sizeSock, dataSock;
    sizeSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    dataSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    // 수신 소켓 주소 정보 설정
    SOCKADDR_IN sizeAddr, dataAddr;
    int sizeAddrSz = sizeof(sizeAddr);
    int dataAddrSz = sizeof(dataAddr);
    ZeroMemory(&sizeAddr, sizeAddrSz);
    sizeAddr.sin_family = AF_INET;
    sizeAddr.sin_addr.s_addr = inet_addr(IP);
    sizeAddr.sin_port = htons(PORT);
    ZeroMemory(&dataAddr, dataAddrSz);
    dataAddr.sin_family = AF_INET;
    dataAddr.sin_addr.s_addr = inet_addr(IP);
    dataAddr.sin_port = htons(PORT);
    // 소켓 옵션 설정 – 수신 버퍼 크기 설정
    int retval, recvBuf = BUFSIZE;
    retval = setsockopt(dataSock, SOL_SOCKET, SO_RCVBUF, (char*)&recvBuf, sizeof(recvBuf));
    printf(Recv buffer size : %d bytes\n, recvBuf);
    // Nagle 알고리즘
    int opt_val = TRUE;
    setsockopt(dataSock, IPPROTO_TCP, TCP_NODELAY, (char*)opt_val, sizeof(opt_val));
    // Connect – 서버 측에 연결 요청
    retval = connect(sizeSock, (SOCKADDR*)&sizeAddr, sizeAddrSz);
    if ((retval = connect(dataSock, (SOCKADDR*)&dataAddr, dataAddrSz)) == SOCKET_ERROR)
        printf(Error : %d\n, WSAGetLastError());
    // 파일 크기 받기
    unsigned int fileSize;
    recv(sizeSock, (char*)&fileSize, sizeof(fileSize), 0);
    // 받은 정보로 파일 생성
    HANDLE hFile2 = CreateFile
    (
        TEXT(recv.mp4),   // 파일명
        GENERIC_WRITE | GENERIC_READ,   // 읽기
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    HANDLE hFileMapping2 = CreateFileMapping
    (
        hFile2,   // 맵 시킬 파일의 핸들
        NULL,   // 보안 설정
        PAGE_READWRITE,   // 파일속성과 맞춤
        0,      // dwMaximumSizeHigh
        fileSize,    // dwMaximumSizeLow
        NULL
    );
    pbFile2 = (char*)MapViewOfFile
    (
        hFileMapping2,
        FILE_MAP_WRITE,
        0,  // 상위 오프셋
        0,
        fileSize
    );
    // 데이터 수신 시작
    DWORD hThreadID;
    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)dataRecv, (SOCKET*)dataSock, 0, &hThreadID);
    WaitForSingleObject(hThread, INFINITE);
    puts(File Data Recving Finish);
    // 받은 파일 사이즈 전송
    unsigned int recvSize = GetFileSize(hFile2, NULL);
    retval = send(dataSock, (char*)&recvSize, sizeof(recvSize), 0);
    end_time = clock(); // 종료 시간 측정
    gap = (float)(end_time  start_time) / (CLOCKS_PER_SEC); // 총 걸린 시간
    printf(“\nTime : %.3f s\n\n, gap);
    printf(“\nReceived File Size : %d bytes\n, recvSize);
    CloseHandle(hFileMapping2);
    CloseHandle(hFile2);
    closesocket(sizeSock);
    closesocket(dataSock);
    WSACleanup();
}
This post is licensed under CC BY 4.0 by the author.

WinSock File Transfer with TCP (Server)

서버의 종류