TCP 파일전송 프로그램
서버정보 localhost(127.0.0.1):7000
송신할 파일정보
이름 Blackpink.jpg
파일크기 415,128 바이트
실행결과
서버
클라이언트
서버 코드
#include <stdio.h>
#include <WinSock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma pack(push, 1)
typedef struct st_PACKET_HEADER
{
DWORD dwPacketCode; // 0x11223344 우리의 패킷확인 고정값
WCHAR szName[32]; // 본인이름, 유니코드 NULL 문자 끝
WCHAR szFileName[128]; // 파일이름, 유니코드 NULL 문자 끝
int iFileSize;
} PACKET_HEADER;
#pragma pack(pop)
int recvn(SOCKET socket, char* buf, int bufSize, int maxSize, int flag);
int main()
{
WSADATA wsaData;
int ret;
ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (ret != 0)
{
wprintf_s(L"error WSAStartup() [%d]\n", ret);
return 1;
}
SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSock == INVALID_SOCKET)
{
wprintf_s(L"error socket() [%d]\n", WSAGetLastError());
return 1;
}
SOCKADDR_IN servAddr;
ZeroMemory(&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(7000);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// bind
if (bind(listenSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
{
wprintf_s(L"error bind() [%d]\n", WSAGetLastError());
return 1;
}
// listen
if (listen(listenSock, 5) == SOCKET_ERROR)
{
wprintf_s(L"error listen() [%d]\n", WSAGetLastError());
return 1;
}
SOCKET clientSock;
SOCKADDR_IN clientAddr;
int addrLen = sizeof(clientAddr);
while (1)
{
// accept
wprintf_s(L"Accept Ready ...\n");
clientSock = accept(listenSock, (SOCKADDR*)&clientAddr, &addrLen);
if (clientSock == INVALID_SOCKET)
{
wprintf_s(L"error accept() [%d]\n", WSAGetLastError());
continue;
}
do
{
// 연결된 소켓정보 출력
wchar_t ipBuf[16];
InetNtopW(clientAddr.sin_family, &clientAddr.sin_addr.s_addr, ipBuf, 16);
wprintf_s(L"Connected IP: %s, Port: %d\n", ipBuf, ntohs(clientAddr.sin_port));
// 헤더 수신
PACKET_HEADER packetHeader;
ret = recvn(clientSock, (char*)&packetHeader, sizeof(packetHeader), sizeof(packetHeader), 0);
if (ret == 0 || ret == SOCKET_ERROR)
{
wprintf_s(L"error recvn header [%d]\n", WSAGetLastError());
break;
}
// 헤더의 패킷코드 확인
if (packetHeader.dwPacketCode != 0x11223344)
{
wprintf_s(L"packet code not equal\n");
break;
}
// 파일 이름 만들기
WCHAR fileName[160];
wsprintfW(fileName, L"%s_%s", packetHeader.szName, packetHeader.szFileName);
// 수신할 데이터 크기만큼 메모리 할당 후 데이터 수신
char* recvData = new char[packetHeader.iFileSize];
ret = recvn(clientSock, recvData, 1000, packetHeader.iFileSize, 0);
if (ret == 0 || ret == SOCKET_ERROR)
{
wprintf_s(L"error recvn() [%d]\n", WSAGetLastError());
delete[] recvData;
break;
}
// 수신한 데이터를 파일로 저장
FILE* file;
ret = _wfopen_s(&file, fileName, L"wb");
if (ret != 0 || file == NULL)
{
wprintf_s(L"error _wfopen_s() [%d]\n", ret);
delete[] recvData;
break;
}
fwrite(recvData, packetHeader.iFileSize, 1, file);
fclose(file);
delete[] recvData;
// 데이터 수신 성공 메시지 송신
int success = 0xdddddddd;
if (send(clientSock, (char*)&success, sizeof(success), 0) == SOCKET_ERROR)
{
wprintf_s(L"error send() [%d]\n", WSAGetLastError());
break;
}
} while (0);
closesocket(clientSock);
}
closesocket(listenSock);
WSACleanup();
return 0;
}
int recvn(SOCKET socket, char* buf, int bufSize, int maxSize, int flag)
{
int size = maxSize;
while (size > 0)
{
int len = size;
if (len > bufSize)
len = bufSize;
len = recv(socket, buf, len, flag);
if (len == 0 || len == SOCKET_ERROR)
return len;
buf += len;
size -= len;
int recvSize = maxSize - size;
wprintf_s(L"recv %d / %d [ %.2f%% ]\n", maxSize, recvSize, (float)recvSize * 100 / maxSize);
}
return maxSize;
}
클라이언트 코드
#include <stdio.h>
#include <WinSock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma pack(push, 1)
typedef struct st_PACKET_HEADER
{
DWORD dwPacketCode; // 0x11223344 우리의 패킷확인 고정값
WCHAR szName[32]; // 본인이름, 유니코드 NULL 문자 끝
WCHAR szFileName[128]; // 파일이름, 유니코드 NULL 문자 끝
int iFileSize;
} PACKET_HEADER;
#pragma pack(pop)
int recvn(SOCKET socket, char* buf, int bufSize, int maxSize, int flag);
int main()
{
WSADATA wsaData;
int ret;
ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (ret != 0)
{
wprintf_s(L"error WSAStartup() [%d]\n", ret);
return 1;
}
SOCKADDR_IN sockAddr;
ZeroMemory(&sockAddr, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(7000);
InetPtonW(sockAddr.sin_family, L"127.0.0.1", &sockAddr.sin_addr);
// 파일 오픈
FILE* file;
ret = _wfopen_s(&file, L"Blackpink.jpg", L"rb");
if (ret != 0 || file == NULL)
{
wprintf_s(L"error _wfopen_s() [%d]\n", ret);
return 1;
}
// 파일 크기 구하기
fseek(file, 0, SEEK_END);
int fileSize = ftell(file);
rewind(file);
// 파일 크기만큼 메모리 할당 후 읽기
char* data = new char[fileSize];
fread_s(data, fileSize, fileSize, 1, file);
fclose(file);
// packet header 만들기
PACKET_HEADER packetHeader;
packetHeader.dwPacketCode = 0x11223344;
wcscpy_s(packetHeader.szName, L"최영진");
wcscpy_s(packetHeader.szFileName, L"Blackpink.jpg");
packetHeader.iFileSize = fileSize;
// socket()
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
wprintf_s(L"error socket() [%d]\n", WSAGetLastError());
return 1;
}
// connect()
ret = connect(sock, (SOCKADDR*)&sockAddr, sizeof(sockAddr));
if (ret == SOCKET_ERROR)
{
wprintf_s(L"error connect() [%d]\n", WSAGetLastError());
return 1;
}
// send header
if (send(sock, (char*)&packetHeader, sizeof(packetHeader), 0) == SOCKET_ERROR)
{
wprintf_s(L"error header send() [%d]\n", WSAGetLastError());
return 1;
}
// send file
int sendSize = 0;
while (sendSize < fileSize)
{
int elementSize = fileSize - sendSize;
if (elementSize > 1000)
elementSize = 1000;
wprintf_s(L"elementSize: %d, ", elementSize);
if (send(sock, data + sendSize, elementSize, 0) == SOCKET_ERROR)
{
wprintf_s(L"error data send() [%d]\n", WSAGetLastError());
break;
}
sendSize += elementSize;
wprintf_s(L"sendSize: %d\n", sendSize);
}
delete[] data;
// recv data
int recvData = 0;
ret = recvn(sock, (char*)&recvData, sizeof(recvData), sizeof(recvData), 0);
if (ret == 0 || ret == SOCKET_ERROR)
{
wprintf_s(L"error recvn() [%d]\n", WSAGetLastError());
return 1;
}
wprintf_s(L"result: %x\n", recvData);
closesocket(sock);
WSACleanup();
wprintf_s(L"== Done ==\n");
return 0;
}
int recvn(SOCKET socket, char* buf, int bufSize, int maxSize, int flag)
{
int size = maxSize;
while (size > 0)
{
int len = size;
if (len > bufSize)
len = bufSize;
len = recv(socket, buf, len, flag);
if (len == 0 || len == SOCKET_ERROR)
return len;
buf += len;
size -= len;
int recvSize = maxSize - size;
wprintf_s(L"recv %d / %d [ %.2f%% ]\n", maxSize, recvSize, (float)recvSize * 100 / maxSize);
}
return maxSize;
}
반응형
'공부' 카테고리의 다른 글
WSAAsyncSelect 모델 서버 프로그래밍 (0) | 2020.10.19 |
---|---|
Select모델 에코서버 프로그래밍 (0) | 2020.10.17 |
TCP 에코서버 프로그래밍 (0) | 2020.10.10 |
내 PC의 backlog 큐 개수 구하기 (2) | 2020.10.08 |
도메인으로 IP 구하기 (0) | 2020.10.08 |