반응형
UDP 통신으로 서버, 클라이언트의 구분이 없는 1대1 채팅 프로그램을 구현하였다.
UDP_ServerDlg.h
public:
CListBox m_msg_list;
CEdit msgEdit;
CEdit rIpEdit;
CEdit rPortEdit;
CEdit mPortEdit;
void InsertMsg(CString str);
afx_msg void ConnectBtnClicked();
afx_msg void SendBtnClicked();
static UINT RecvFunc(LPVOID pParam);
private:
SOCKET remote_socket;
SOCKET my_socket;
SOCKADDR_IN my_addr;
SOCKADDR_IN remote_addr;
UDP_ServerDlg.cpp
// 연결 버튼 클릭 함수
void CUDPServerDlg::ConnectBtnClicked()
{
UINT mPort;
CString strPort;
mPortEdit.GetWindowText(strPort); // 사용자 입력 포트
mPort = _tstoi(strPort);
// 자신 ip 가져오기
char myaddr[20] = "";
gethostname(myaddr, sizeof(myaddr));
PHOSTENT hostInfo = gethostbyname(myaddr);
SOCKADDR_IN addr;
CArray<sockaddr_in, sockaddr_in& > ipArray;
CString msgIp("");
if (hostInfo) {
for (int i = 0; hostInfo->h_addr_list[i] != NULL; i++) {
memcpy(&addr.sin_addr, hostInfo->h_addr_list[i], hostInfo->h_length);
ipArray.Add(addr);
}
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(mPort);
my_addr.sin_addr.s_addr = ipArray.GetAt(0).sin_addr.s_addr;
// my_addr.sin_addr.s_add = htonl(INADDR_ANY) : 127.0.0.1로 설정
UINT rPort;
CString strPort2;
rPortEdit.GetWindowText(strPort2); // 사용자 입력 상대 포트
rPort = _tstoi(strPort2);
TCHAR rIp[20];
rIpEdit.GetWindowTextA(rIp, 20); // 사용자 입력 상대 ip
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(rPort);
remote_addr.sin_addr.s_addr = inet_addr(rIp);
my_socket = socket(PF_INET, SOCK_DGRAM, 0); // 자신 소켓 생성
if (my_socket == INVALID_SOCKET) InsertMsg("my socket error");
if (bind(my_socket, (SOCKADDR*)&my_addr, sizeof(my_addr)) == -1) // 소켓 bind()
{
InsertMsg(_T("bind error"));
return;
}
remote_socket = socket(PF_INET, SOCK_DGRAM, 0); // 상대 소켓 생성
if (remote_socket == INVALID_SOCKET)
{
InsertMsg("remote socket error");
return;
}
InsertMsg(_T("Address Setting Complete"));
AfxBeginThread(RecvFunc, this); // 수신 스레드 시작
}
반응형
// 수신 스레드
UINT CUDPServerDlg::RecvFunc(LPVOID pParam) {
CUDPServerDlg* pDlg = (CUDPServerDlg*)pParam;
while (1)
{
char temp[1024] = "";
int strlen;
// 메시지 수신, 수신한 메시지 길이 반환
strlen = recvfrom(pDlg->my_socket, temp, sizeof(temp), 0, NULL, NULL);
if (strlen == -1) // 오류
{
pDlg->InsertMsg("read error");
break;
}
else // 메시지 정상 수신
{
CString str = (LPSTR)temp;
pDlg->InsertMsg(str); // 메시지 ListBox에 추가
}
}
closesocket(pDlg->my_socket);
return 0;
}
// 전송 버튼 클릭 함수
void CUDPServerDlg::SendBtnClicked()
{
CString msg, str;
msgEdit.GetWindowText(msg);
InsertMsg("ME : " + msg); // 자신이 보낸 메시지 ListBox 추가
// 메시지 보낼 때 User (ip : port)로 보이도록 메시지 가공
str.Format(_T("User (%s : %d) : "), inet_ntoa(my_addr.sin_addr), ntohs(my_addr.sin_port));
msg = str + msg;
int len = msg.GetLength();
char* message = new char[len + 10];
strcpy(message, msg.GetBuffer(0));
// 상대에게 메시지 전송
if (sendto(remote_socket, message, 1024, 0, (SOCKADDR*)&remote_addr, sizeof(remote_addr)) == -1)
{
InsertMsg("send error");
}
else
{
msgEdit.SetWindowTextA("");
}
}
// 메시지 ListBox 추가 함수
void CUDPServerDlg::InsertMsg(CString str)
{
m_msg_list.InsertString(-1, str);
m_msg_list.SetTopIndex(m_msg_list.GetCount() - 1);
}
반응형
'C++ > 예제' 카테고리의 다른 글
[C++][MFC] UDP 통신 (2) 채팅 프로그램 멀티캐스트 예제 (7) | 2022.09.19 |
---|---|
[C++][MFC] TCP/IP 통신 (2) 채팅 프로그램 클라이언트 예제 (1) | 2022.09.17 |
[C++][MFC] TCP/IP 통신 (1) 채팅 프로그램 서버 예제 (1) | 2022.09.17 |
[C][C++] 배열을 활용한 바이트 스왑 예제 (0) | 2022.04.07 |
댓글