🧼C, C++/네트워크
소켓 파일전송 C++ #3
개발환경 >> Visual Studio
언어 >> C++20
운영체제 >> Windows10
안녕하세요!!!
이번에는 엄청난 파일전송속도와 안정성을 가지고 왔습니다.
나중에는 이것보다 더 체계적으로 설계해서 속도와 안정성을 더 올려보겠습니다!
일단 현재 안정성은 최고치구요.
속도만 더 올리고싶네요!~~
{[ 서버 ]}
/*
* RECEIVER
*/
#define PKT 1024 //기본 데이터패킷사이즈
#define FILEMAX 100000 //파일데이터 한 단위별 패킷사이즈
#pragma comment(lib, "ws2_32.lib") //ws2_32.a 링킹
#include <winsock2.h> //윈속
#include <windows.h> //윈도우api
#include <iostream> //c++표준입출력
#include <string> //getline함수와 string클래스
int main() {
WSADATA wsa;
if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0) return -1; //wsa !(0)일시 종료
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //소켓 tcpip
if (server == INVALID_SOCKET) return -1; //종료
SOCKADDR_IN addr = { 0 }; //소켓구조체
addr.sin_addr.s_addr = htonl(INADDR_ANY); //주소
addr.sin_port = htons(8080); //포트
addr.sin_family = AF_INET; //데이터 체계방식
if(bind(server, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) return -1; //바인딩
if (listen(server, SOMAXCONN) == SOCKET_ERROR) return -1; //리스닝
SOCKADDR_IN clientaddr = { 0 }; //클라이언트 수용구조체
int clientsize = sizeof(clientaddr); //클라이언트 크기
SOCKET client = accept(server, (SOCKADDR*)&clientaddr, &clientsize); //클라이언트 오브젝트
if (client == INVALID_SOCKET) return -1; //종료
FILE* fp = 0;
std::string str;
char buffer[PKT],
FileR[FILEMAX],
name[PKT];
while (true) {
ZeroMemory(name, PKT);
ZeroMemory(buffer, PKT);
str.clear();
std::cout << "Type to load filename by client path : "; //클라이언트쪽 받아올 파일절대경로 입력
std::getline(std::cin, str); //(띄어쓰기포함o)
fflush(stdin);
std::cout << "Set the filename will save : "; //서버쪽 생성될 파일이름과 확장자 입력
std::cin >> name; //(띄어쓰기포함x)
fflush(stdin);
send(client, str.c_str(), PKT, 0); //클라이언트쪽으로 파일경로 전송
recv(client, buffer, PKT, 0); //파일크기 받기
fopen_s(&fp, name, "wb"); //쓰기전용으로 열기
int filesize = atoi(buffer); //형변환
while (true) {
ZeroMemory(FileR, FILEMAX);
ZeroMemory(buffer, PKT);
recv(client, buffer, PKT, 0); //파일데이터크기 받기
recv(client, FileR, atoi(buffer), 0); //파일데이터 받기
fwrite(FileR, sizeof(char), atoi(buffer), fp); //파일 데이터 쓰기
std::cout << "received " << buffer << " bytes." << std::endl;
filesize -= atoi(buffer); //전체파일사이즈를 받아온 파일사이즈만큼 줄인다
if (filesize <= 0) break; //만약 파일사이즈가 0보다 작거나 같을경우 break
}
fclose(fp);
}
closesocket(client);
closesocket(server);
WSACleanup();
}
{[ 클라이언트 ]}
/*
* SENDER
*/
////////////////////////아래 서버쪽에서 설명한쪽은 주석을 생략하겠습니다.
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define PKT 1024
#define FILEMAX 100000
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <windows.h>
#include <iostream>
int main() {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) return -1;
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET) return -1;
SOCKADDR_IN addr = { 0 };
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(8080);
addr.sin_family = AF_INET;
while (connect(server, (SOCKADDR*)&addr, sizeof(addr)));
FILE* fp = 0;
char buffer[PKT],
FileR[FILEMAX];
int filesize, recvdsize;
while (true) {
ZeroMemory(buffer, PKT);
recv(server, buffer, PKT, 0);
if (WSAGetLastError()) return -1; //서버나갔을때 발생할 fseek에러 방지
std::cout << "filepath >> " << buffer << std::endl;
fopen_s(&fp, buffer, "rb"); //읽기전용으로 열기
fseek(fp, 0, SEEK_END); //파일포인터 제일끝으로가서
filesize = ftell(fp); //사이즈재기
fseek(fp, 0, SEEK_SET); //파일포인터 다시 처음으로오기
std::cout << "filesize >> " << filesize << std::endl;
ZeroMemory(buffer, PKT); //현재 buffer에 파일경로값들어있으니까 초기화
sprintf_s(buffer, "%d", filesize); //형변환
send(server, buffer, PKT, 0); //파일크기 전송
while (true) {
ZeroMemory(buffer, PKT);
ZeroMemory(FileR, FILEMAX);
//실제로 받아온크기 = fread(파일데이터받아올객체, 그 객체의 한개단위, 총크기, 파일포인터)
recvdsize = fread(FileR, sizeof(char), FILEMAX, fp);
_itoa_s(recvdsize, buffer, 10); //형변환
send(server, buffer, PKT, 0); //데이터크기전송
send(server, FileR, recvdsize, 0); //데이터전송
std::cout << "sending " << recvdsize << " bytes." << std::endl;
filesize -= recvdsize; //파일 전체사이즈는 읽어들인 사이즈만큼 뺀다
if (filesize <= 0) break; //파일전체사이즈가 0보다 작거나같을시 break
}
fclose(fp);
}
closesocket(server);
WSACleanup();
}
그럼 봐주셔서
감사합니다!
궁금한 부분이 있다면 댓글로 질문주세요!
방금 생각났는데 다음 4번째 파일전송 시리즈는 쓰레드를 이용해서 병렬로 파일전송을 하도록해봐야겠네요~!
그때 사용될 소켓개념은 다중스트림서버 정도 되겠네요!
'🧼C, C++ > 네트워크' 카테고리의 다른 글
IOCP 에코 서버-클라이언트 C++ (CompletionQueue) (0) | 2021.09.08 |
---|---|
소켓 파일전송 프로그램 C++ #4 (6) | 2021.01.21 |
다중 스트림서버 C++ TCP #1 (0) | 2020.12.31 |
다중 클라이언트 C++ TCP #3 (수정본) (2) | 2020.12.24 |
소켓 파일전송 C++ #2 (0) | 2020.11.26 |
댓글