🧼C, C++/네트워크

실시간 채팅 프로그램 C++ TCP

Mawile 2020. 10. 1.
728x90

안녕하세요!

이번에는 멀티쓰레드와 소켓을 이용해

실시간 채팅프로그램을 아주쉽게만들어보겠습니다!!!

(오예~~)

 

 

C++ TCP 기본강좌

 

소켓 데이터 C++ TCP

시작하기 앞서서 STDC++11,14에서 정상작동이 확인되었습니다. IDE는 DeVcpp을 사용했습니다.  " 이글은 윈도우소켓 기본 C++ TCP " 글의 다음글임을 참고해주세요! 이번에는 ! 서버와 클라이언트간의 ��

mawile.tistory.com

참고자료

 

thread - C++ Reference

main, foo and bar now execute concurrently... foo and bar completed.

www.cplusplus.com

 

최근글

https://mawile.tistory.com/191

 

IOCP 에코 서버-클라이언트 C++ (CompletionQueue)

오랜만에 네트워크관련글을 쓰게되었습니다. 사실 반년전에는 네트워크관련글을 열심히올리다가, 대부분 알고리즘&게임엔진에 대한 글을 많이쓰게되었습니다. 그리고, 현재.. TCP/IP IOCP 에코서

mawile.tistory.com

 


먼저 소켓서버와 클라이언트 기본은 저가 전에 소켓기본에 대해 소개한 곳에서 소스를 사용할게요!

[[[   서버 기본 틀   ]]]

#include <iostream>
#include <winsock2.h>
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_STREAM,IPPROTO_TCP);

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

bind(skt, (SOCKADDR*)&addr,sizeof(addr));
listen(skt,SOMAXCONN);

SOCKADDR_IN client = {};
int client_size = sizeof(client);
ZeroMemory(&client,client_size);
client_sock = accept(skt,(SOCKADDR*)&client,&client_size);

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

 

[[[   클라이언트 기본 틀   ]]]

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

#define PACKET_SIZE 1024

SOCKET skt;

int main(){
	WSADATA wsa;
	WSAStartup(MAKEWORD(2,2),&wsa);

	skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

	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(1){
		if(!connect(skt, (SOCKADDR*)&addr,sizeof(addr))) break;
	}
    
	closesocket(skt);
	WSACleanup();
}

시작하겠습니다....!

 

 

먼저 시작하기앞서서 멀티쓰레드를 사용할수있게해주기위해

#include <thread>  이렇게 적어줄게요!

그다음 thread변수를 만들어줍니다!!

[[[   클라이언트   ]]]

#include <iostream>
#include <winsock2.h>
#include <thread> //멀티쓰레드를 사용하기위한!!!
using namespace std;

#define PACKET_SIZE 1024

SOCKET skt;

int main(){
	WSADATA wsa;
	WSAStartup(MAKEWORD(2,2),&wsa);

	skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

	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(1){
		if(!connect(skt, (SOCKADDR*)&addr,sizeof(addr))) break;
	}
	thread proc1(proc_recv);
    //proc1이라는 이름의 thread변수를만들어 "proc_recv"라는함수를 멀티쓰레드로 사용할겁니다
	char buffer[PACKET_SIZE] = {0};

	while(!WSAGetLastError()){ //메세지전송
		cin >> buffer;
		send(skt, msg,strlen(buffer),0);
	}
	proc1.join();
    //proc1이라는 쓰레드변수가 이 함수에서 끝날때까지 기다립니다!
	closesocket(skt);
	WSACleanup();
}

저가 새로 추가한부분은 주석을 추가할게요

잘 봐주세요!

[[[   서버   ]]]

#include <iostream>
#include <winsock2.h>
#include <thread>
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_STREAM,IPPROTO_TCP);

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

bind(skt, (SOCKADDR*)&addr,sizeof(addr));
listen(skt,SOMAXCONN);

SOCKADDR_IN client = {};
int client_size = sizeof(client);
ZeroMemory(&client,client_size);
client_sock = accept(skt,(SOCKADDR*)&client,&client_size);

char buffer[PACKET_SIZE] = {0};
thread proc2(proc_recvs);

while(!WSAGetLastError()){ //메세지전송
cin >> buffer;
send(client_sock,buffer,strlen(buffer),0);
}

proc2.join();
closesocket(client_sock);
closesocket(skt);
WSACleanup();
}

 

 

 

 

이제 드디어 데이터를 받아올 쓰레드를

proc_recvs와 proc_recv라는 이름으로 각각 받아오겠습니다!

 

[[[   클라이언트   ]]]

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

#define PACKET_SIZE 1024

SOCKET skt;

void proc_recv(){
	char buffer[PACKET_SIZE] = {}; //char 생성
	string cmd; //string 생성
	while(!WSAGetLastError()){
		ZeroMemory(&buffer,PACKET_SIZE); //buffer 비우기
		recv(skt, buffer, PACKET_SIZE,0); //데이터받아오기
		cmd=buffer; //buffer의값이 cmd에 들어갑니다
		if(cmd=="hi") break; //cmd의값이 "exit"일경우 데이터받아오기'만' 종료
		cout << "받은 메세지: " << buffer << endl;
	}
}

int main(){
	WSADATA wsa;
	WSAStartup(MAKEWORD(2,2),&wsa);

	skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

	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(1){
		if(!connect(skt, (SOCKADDR*)&addr,sizeof(addr))) break;
	}
	thread proc1(proc_recv);
	char msg[PACKET_SIZE] = {0};

	while(!WSAGetLastError()){
		cin >> msg;
		send(skt, msg,strlen(msg),0);
	}
	proc1.join();
	closesocket(skt);
	WSACleanup();
}

 

[[[   서버   ]]]

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

#define PACKET_SIZE 1024
SOCKET skt,client_sock;

void proc_recvs(){
	char buffer[PACKET_SIZE] = {0};

	while(!WSAGetLastError()){ //여긴 일부로 차이점을 일부러 exit나 이런 이벤트 안넣었습니다
		ZeroMemory(&buffer,PACKET_SIZE);
		recv(client_sock, buffer, PACKET_SIZE,0);
		cout << "받은 메세지: " << buffer << endl;
	}
}

int main(){
WSADATA wsa;
WSAStartup(MAKEWORD(2,2), &wsa);

skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

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

bind(skt, (SOCKADDR*)&addr,sizeof(addr));
listen(skt,SOMAXCONN);

SOCKADDR_IN client = {};
int client_size = sizeof(client);
ZeroMemory(&client,client_size);
client_sock = accept(skt,(SOCKADDR*)&client,&client_size);

char buffer[PACKET_SIZE] = {0};
thread proc2(proc_recvs);

while(!WSAGetLastError()){
cin >> buffer;
send(client_sock,buffer,strlen(buffer),0);
}
proc2.join();
closesocket(client_sock);
closesocket(skt);
WSACleanup();
}

 


자 이렇게 완성했습니다!

밑에 시연영상과

오늘은 파일을 바로올려놓겠습니다

감사합니다!

 

 

 

thread_client.cpp
0.00MB
thread_client.exe
1.91MB
thread_server.cpp
0.00MB
thread_server.exe
1.91MB

 

 

 

 

 

728x90

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

소켓 기본 틀 #1  (0) 2020.10.05
리버스 쉘 Reverse Shell C++  (0) 2020.10.05
백도어 만들기 C++ TCP  (0) 2020.09.26
소켓 데이터 C++ TCP  (0) 2020.09.24
소켓 기본 C++ TCP  (0) 2020.09.18

댓글