🧼C, C++/네트워크

소켓 구조체 정보 전송 C++ TCP

Mawile 2020. 10. 16.
728x90

시작하기 앞서서 사용한 운영체제는 Windows10이며IDE는 DevCpp이고 사용한 언어는 C++11입니다!


안녕하세요!!

 

이번에는 간단명료하게 원리 설명과 소스코드 뿌리고 빠지겠습니다~!!(ㅋㅋㅋㅋ)

궁금한 부분이 있다면 모두 질문 주세요~!!!!!!!!!!!!!

 


[[   참고자료   ]]

 

소켓 기본 틀 #1

[[[  서버 기본 틀  ]]] #include #include using namespace std; #define PACKET_SIZE 1024 SOCKET skt,client_sock; int main(){ WSADATA wsa; WSAStartup(MAKEWORD(2,2), &wsa); skt = socket(PF_INET,SOCK_S..

mawile.tistory.com

 

 

소켓 기본 틀 #2

[[[  서버  ]]] #include #include using namespace std; #define PACKET_SIZE 1024 int main(){ WSADATA wsa; if(WSAStartup(MAKEWORD(2,2), &wsa)!=0){ cout << "WSA error"; return 0; } SOCKET skt; skt = s..

mawile.tistory.com

 

 

멀티쓰레딩 <C++ thread>

시작하기 앞서서 사용한 운영체제는 Windows10이며 IDE는 DevCpp이고 사용한언어는 C++11입니다! 안녕하세요! 멀티쓰레딩관련 첫 번째 글이네요! 먼저 멀 티쓰 레딩 시리즈는 thread->atomic->mutex->chrono->p_t

mawile.tistory.com


 

이번에도 역시 "소켓 기본 틀 #2"를 사용하였습니다!

[[   서버#1   ]]

#include <iostream>
#include <winsock2.h>
using namespace std;

#define PACKET_SIZE 1024

typedef struct _type{
	int das;
	char test[PACKET_SIZE];
}type; //int형과 char*형을 저장한 구조체

int main(){
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2,2), &wsa)!=0){
		cout << "WSA error";
		return 0;
	}

	SOCKET skt;
	skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(skt==INVALID_SOCKET){
		cout << "socket error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}

	SOCKADDR_IN addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(4444);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(skt, (SOCKADDR*)&addr,sizeof(addr))==SOCKET_ERROR){
		cout << "bind error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}
	if(listen(skt,SOMAXCONN)==SOCKET_ERROR){
		cout << "listen error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}

	SOCKADDR_IN client = {0};
	int client_size = sizeof(client);

	SOCKET client_sock;
	client_sock = accept(skt,(SOCKADDR*)&client,&client_size);
	if(client_sock==INVALID_SOCKET){
		cout << "accept error";
		closesocket(client_sock);
		closesocket(skt);
		WSACleanup();
		return 0;
	}
	
	type tp;
	char buf[PACKET_SIZE];
	while(1){
		cin >> buf;
		tp.das = atoi(buf); //데이터저장
		cin >> buf;
		strcpy(tp.test,buf); //데이터저장
		send(client_sock,(char*)&tp,PACKET_SIZE,0); //구조체 형변환
	}

	closesocket(client_sock);
	closesocket(skt);
	WSACleanup();
}

 

[[   클라이언트#1   ]]

#include <iostream>
#include <winsock2.h>
#include <thread>
using namespace std;

#define PACKET_SIZE 1024

typedef struct _type{
	int das;
	char test[PACKET_SIZE];
}type;
type *tp; //구조체 전체로 정의

void reada(SOCKET &s){
	char buf[PACKET_SIZE];
	while(1){
		recv(s,buf,PACKET_SIZE,0);
		tp = (type*)buf; //형변환
	}
}

int main(){
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
		cout << "WSA error";
		WSACleanup();
		return 0;
	}

	SOCKET skt;
	skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(skt==INVALID_SOCKET){
		cout << "socket error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}

	SOCKADDR_IN addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(4444);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	
	while(connect(skt, (SOCKADDR*)&addr,sizeof(addr)));
	
	thread (reada,ref(skt)).detach();
	
	char dasd[PACKET_SIZE];
	
	while(1){
		cin >> dasd;
		cout << "int: " << tp->das << endl;
		cout << "char*: " << tp->test << endl;
	}
    
	closesocket(skt);
	WSACleanup();
}

 

 

int형과 char형을 순서대 로저 장하고 그 데이터를 클라이언트로 전송한 뒤,

클라이언트 측에서 멀티스레드로 계속 정보를 받아오면서

아무 키나 누를 시 그 구조체의 정보를 확인할 수 있게 했고요

정상 작동되네요!

 

             서버(왼쪽) ------------ 클라이언트(오른쪽)

 

일단 구조체 정보를 전송하는 거는 이렇게 하는데..

만약 구조체 배열을 전송하려면 어떻게 소스코드가 변할까요?

 

 

서버#2   ]]

#include <iostream>
#include <winsock2.h>
using namespace std;

#define PACKET_SIZE 1024
#define MAX 5

typedef struct _type{
	int das;
	char test[PACKET_SIZE];
}type;

int main(){
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2,2), &wsa)!=0){
		cout << "WSA error";
		return 0;
	}

	SOCKET skt;
	skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(skt==INVALID_SOCKET){
		cout << "socket error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}

	SOCKADDR_IN addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(4444);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(skt, (SOCKADDR*)&addr,sizeof(addr))==SOCKET_ERROR){
		cout << "bind error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}
	if(listen(skt,SOMAXCONN)==SOCKET_ERROR){
		cout << "listen error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}

	SOCKADDR_IN client = {0};
	int client_size = sizeof(client);

	SOCKET client_sock;
	client_sock = accept(skt,(SOCKADDR*)&client,&client_size);
	if(client_sock==INVALID_SOCKET){
		cout << "accept error";
		closesocket(client_sock);
		closesocket(skt);
		WSACleanup();
		return 0;
	}
	
	type *tp = new type[MAX]; //MAX만큼 동적할당
	char buf[PACKET_SIZE];
	while(1){
		for(int i=0;i<MAX;i++){
			cin >> (tp+i)->das >> (tp+i)->test; // 구조체내용 입력
		}
		for(int i=0;i<MAX;i++) send(client_sock,(char*)&tp[i],PACKET_SIZE,0);
        //차례대로 구조체정보 보내기
	}

	closesocket(client_sock);
	closesocket(skt);
	WSACleanup();
	delete[] tp;
}

 

[[   클라이언트#2   ]]

#include <iostream>
#include <winsock2.h>
#include <thread>
using namespace std;

#define PACKET_SIZE 1024
#define MAX 5

typedef struct _type{
	int das;
	char test[PACKET_SIZE];
}type;
type *tp;

void reada(SOCKET &s){
	char buf[PACKET_SIZE];
	while(1){
		for(int i=0;i<MAX;i++){
			recv(s,buf,PACKET_SIZE,0); // 구조체정보 차례대로 받기
			memcpy(&tp[i],buf,PACKET_SIZE); // 메모리복사
		}
	}
}	

int main(){
	WSADATA wsa;
	if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
		cout << "WSA error";
		WSACleanup();
		return 0;
	}

	SOCKET skt;
	skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(skt==INVALID_SOCKET){
		cout << "socket error";
		closesocket(skt);
		WSACleanup();
		return 0;
	}

	SOCKADDR_IN addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(4444);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	
	while(connect(skt, (SOCKADDR*)&addr,sizeof(addr)));
	
	thread (reada,ref(skt)).detach();
	
	char dasd[PACKET_SIZE];
	int i;
	tp = new type[MAX]; // MAX만큼 동적할당
	while(1){
		cin >> dasd;
		for(i=0;i<MAX;i++){ //아무거나 입력시 내용출력
			cout << "int: " << (tp+i)->das << endl;
			cout << "char*: " << (tp+i)->test << endl;
			cout << "\n\n";
		}	
	}
    
	closesocket(skt);
	WSACleanup();
	delete[] tp;
}

 

        클라이언트(왼쪽) --------서버(오른쪽)

 

 

그리고 "(tp+i)->das"는 "tp [i]. das"와 같은 표현입니다!

송수신 데이터 크기는 반드시 char형 버퍼의 크기로 통일해주세요!

 

 

이번 꺼는 심플해서 따로 소스코드 같은 거 안 올려놓겠습니다

궁금한 부분이 있다면 댓글로 질문 주세요!

그러면 긴 글 봐주셔서 감사합니다~!!

 

 


 

728x90

'🧼C, C++ > 네트워크' 카테고리의 다른 글

다중 클라이언트 C++ TCP #2  (2) 2020.11.05
소켓 버퍼 비우기 C++  (0) 2020.10.17
다중 클라이언트 C++ TCP #1  (0) 2020.10.14
소켓 기본 틀 #2  (1) 2020.10.13
소켓 파일전송 C++ #1  (0) 2020.10.06

댓글