🧼C, C++/네트워크
소켓 파일전송 프로그램 C++ #4
개발환경 >> Visual Studio
언어 >> C++20
운영체제 >> Windows10
안녕하세요
어제 파일전송 #3을 만들고 할거없어서 그냥 바로 또 #4 만들었습니다 ㅋㅋ
#4는 어떤기능을 추가했냐면, 파일을 이제 다중으로 동시에 여러파일을 받아올 수 있게 설계했습니다.
그럼 시작하겠습니다!
( 하단에 다운로드링크로 배포중인 배포파일내에 소스파일과 블로그에서 소스파일은 일부 다릅니다.
이유는 블로그 포스팅하면서 좀 수정함 ㅋㅋ. 그래서 다시 압축하고 재배포하기 귀찮아서 ㅋㅋ )
{[ 추천강좌 ]}
{[ 다운로드 ]}
{[ 서버 ]}
#include "Sheader.h"
void FileTransfer(SOCKET client, const char* filepath, const char* filename) {
FILE* fp = 0;
std::string str;
char buffer[PKT] = { 0 },
FileR[FILEMAX] = { 0 },
name[PKT] = { 0 };
send(client, filepath, PKT, 0);
recv(client, buffer, PKT, 0);
fopen_s(&fp, filename, "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;
}
std::cout << "Input a command (send_data , add_stream): ";
fclose(fp);
}
SOCKET recvClient() {
WSADATA wsa;
SOCKET server, client;
SOCKADDR_IN addr = { 0 }, clientaddr = { 0 };
int clientsize;
WSAStartup(MAKEWORD(2, 2), &wsa);
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(MasterPort);
addr.sin_family = AF_INET;
bind(server, (SOCKADDR*)&addr, sizeof(addr));
listen(server, SOMAXCONN);
std::cout << "MasterClient connecting..." << std::endl;
clientsize = sizeof(clientaddr);
client = accept(server, (SOCKADDR*)&clientaddr, &clientsize);
std::cout << "MasterClient connected !" << std::endl;
std::cout << "Input a command (send_data , add_stream): ";
return client;
}
int main() {
SOCKET client = recvClient();
std::string str;
char filename[PKT],
command[PKT];
int num;
while (true) {
str.clear();
ZeroMemory(command, PKT);
ZeroMemory(filename, PKT);
std::cin >> command;
if (!strcmp(command, "add_stream")) std::thread([&]() {
streams.push_back(stream(client, BasePort + clientcnt));
std::cout << "Created a stream number " << clientcnt << std::endl;
clientcnt += 1;
std::cout << "Input a command (send_data , add_stream): ";
} ).detach();
else if (!strcmp(command, "send_data")) {
std::cout << "Input a stream number: ";
std::cin >> num;
if (num > clientcnt - 1) continue;
send(client, "sends", PKT, 0);
ZeroMemory(command, PKT);
_itoa_s(num, command, 10);
send(client, command, PKT, 0);
std::cout << "Input a filepath on client: ";
std::cin.ignore();
std::getline(std::cin, str);
std::cout << "Input a filename on server: ";
std::cin >> filename;
pdd.push_back(Pdata(str.c_str(), filename));
pddcnt += 1;
std::thread(FileTransfer, streams[num].GetClient(), pdd[pddcnt-1].filepath, pdd[pddcnt-1].filename).detach();
}
}
}
{[ 서버 헤더파일 ]}
/*
* RECEIVER
*/
#pragma once
#pragma comment(lib, "ws2_32.lib")
#define PKT 1024
#define FILEMAX 100000
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <thread>
const int MasterPort = 4321;
int BasePort = 8080, clientcnt = 0, pddcnt = 0;
class stream {
private:
WSADATA wsa;
SOCKET server, client;
SOCKADDR_IN addr = { 0 }, clientaddr = { 0 };
int clientsize;
public:
stream() { }
stream(SOCKET s, int port) {
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) return;
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET) return;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
if (bind(server, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) return;
if (listen(server, SOMAXCONN) == SOCKET_ERROR) return;
send(s, "adds", PKT, 0);
std::cout << "Listening from client... " << port - BasePort << std::endl;
clientsize = sizeof(clientaddr);
client = accept(server, (SOCKADDR*)&clientaddr, &clientsize);
if (client == INVALID_SOCKET) return;
std::cout << "Joined a client number " << port - BasePort << std::endl;
}
SOCKET& GetClient() { return this->client; }
}; std::vector<stream>streams;
typedef struct __data_T {
char filepath[PKT] = { 0 },
filename[PKT] = { 0 };
int number;
__data_T() { }
__data_T(const char* f1, const char* f2) {
strcpy_s(filepath, f1);
strcpy_s(filename, f2);
}
}Pdata; std::vector<Pdata>pdd;
{[ 클라이언트 ]}
#include "Cheader.h"
void FileTransfer(SOCKET server) {
FILE* fp = 0;
char buffer[PKT],
FileR[FILEMAX];
int filesize, recvdsize;
ZeroMemory(buffer, PKT);
recv(server, buffer, PKT, 0);
std::cout << "received filepath => " << buffer << std::endl;
fopen_s(&fp, buffer, "rb");
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
std::cout << "received filesize => " << filesize << std::endl;
ZeroMemory(buffer, PKT);
sprintf_s(buffer, "%d", filesize);
send(server, buffer, PKT, 0);
while (true) {
ZeroMemory(buffer, PKT);
ZeroMemory(FileR, FILEMAX);
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;
}
fclose(fp);
}
void addStreams(SOCKET client) {
char buffer[PKT],
num[PKT];
while (true) {
ZeroMemory(buffer, PKT);
recv(client, buffer, PKT, 0);
if (!strcmp(buffer, "adds")) {
streams.push_back(stream(BasePort + clientcnt));
std::cout << "Created a stream number " << clientcnt << std::endl;
clientcnt += 1;
}
else if (!strcmp(buffer, "sends")) {
ZeroMemory(num, PKT);
recv(client, num, PKT, 0);
std::thread(FileTransfer, streams[atoi(num)].GetServer()).detach();
}
}
}
SOCKET Master() {
std::cout << "Input the server ip address: ";
std::cin >> IP;
WSADATA wsa;
SOCKET server;
SOCKADDR_IN addr = { 0 };
WSAStartup(MAKEWORD(2, 2), &wsa);
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
addr.sin_addr.s_addr = inet_addr(IP);
addr.sin_port = htons(MasterPort);
addr.sin_family = AF_INET;
std::cout << "Connecting to MasterServer..." << std::endl;
while (connect(server, (SOCKADDR*)&addr, sizeof(addr)));
std::cout << "Connected to MasterServer !" << std::endl;
return server;
}
int main() {
SOCKET server = Master();
std::thread(addStreams, server).detach();
while (true);
closesocket(server);
WSACleanup();
}
{[ 클라이언트 헤더파일 ]}
/*
* SENDER
*/
#pragma once
#pragma comment(lib, "ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define PKT 1024
#define FILEMAX 100000
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <thread>
char IP[PKT] = { 0 };
const int MasterPort = 4321;
int BasePort = 8080, clientcnt = 0;
void t(const char* chr) {
std::cout << chr << std::endl;
}
class stream {
private:
WSADATA wsa;
SOCKET server;
SOCKADDR_IN addr = { 0 };
public:
stream() { }
stream(int port) {
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) return;
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET) return;
addr.sin_addr.s_addr = inet_addr(IP);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
std::cout << "Connecting to server... " << port - BasePort << std::endl;
while (connect(server, (SOCKADDR*)&addr, sizeof(addr)));
std::cout << "Connected to server ! " << port - BasePort << std::endl;
}
SOCKET& GetServer() { return this->server; }
}; std::vector<stream>streams;
{[ 시연영상 ]}
궁금한 부분있으면 댓글로 질문 주세요 ㅠㅠ!!
그럼 봐주셔서 감사합니다~!
'🧼C, C++ > 네트워크' 카테고리의 다른 글
c/c++ 메일 전송(smtp프로토콜) | 이론과 실습 (4) | 2021.12.25 |
---|---|
IOCP 에코 서버-클라이언트 C++ (CompletionQueue) (0) | 2021.09.08 |
소켓 파일전송 C++ #3 (0) | 2021.01.20 |
다중 스트림서버 C++ TCP #1 (0) | 2020.12.31 |
다중 클라이언트 C++ TCP #3 (수정본) (2) | 2020.12.24 |
댓글