본문 바로가기
프로그래밍/MFC

UDP 소켓 통신

by 완소루피 2020. 11. 12.
728x90
반응형

헤더파일

// SocketTestClientDlg.h : header file 

// 


#pragma once 



// CSocketTestClientDlg dialog 

class CSocketTestClientDlg : public CDialog 

{ 

// Construction 

public: 

CSocketTestClientDlg(CWnd* pParent = NULL); // standard constructor 


// Dialog Data 

enum { IDD = IDD_SOCKETTESTCLIENT_DIALOG }; 


protected: 

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 



// Implementation 

protected: 

HICON m_hIcon; 


// Generated message map functions 

virtual BOOL OnInitDialog(); 

afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 

afx_msg void OnPaint(); 

afx_msg HCURSOR OnQueryDragIcon(); 

DECLARE_MESSAGE_MAP() 

public: 

CString m_senddata; 

CString m_recvData; 

afx_msg void OnBnClickedOk(); 

afx_msg void OnBnClickedCancel(); 

int m_portno; 

CString m_udpserver; 

}; 

 

 

CPP 파일

// SocketTestClientDlg.cpp : implementation file 

// 


#include "stdafx.h" 

#include "SocketTestClient.h" 

#include "SocketTestClientDlg.h" 

#include <string> 



// CSocketTestClientDlg dialog 



CSocketTestClientDlg::CSocketTestClientDlg(CWnd* pParent /*=NULL*/) 

: CDialog(CSocketTestClientDlg::IDD, pParent) 

, m_senddata(_T("")) 

, m_recvData(_T("")) 

, m_portno(1819) 

, m_udpserver(_T("localhost")) 

{ 

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 

} 


void CSocketTestClientDlg::DoDataExchange(CDataExchange* pDX) 

{ 

CDialog::DoDataExchange(pDX); 

DDX_Text(pDX, IDC_EDIT2, m_senddata); 

DDX_Text(pDX, IDC_EDIT1, m_recvData); 

DDX_Text(pDX, IDC_EDIT4, m_portno); 

DDX_Text(pDX, IDC_EDIT3, m_udpserver); 

} 


BEGIN_MESSAGE_MAP(CSocketTestClientDlg, CDialog) 

ON_WM_SYSCOMMAND() 

ON_WM_PAINT() 

ON_WM_QUERYDRAGICON() 

//}}AFX_MSG_MAP 

ON_BN_CLICKED(IDOK, &CSocketTestClientDlg::OnBnClickedOk) 

ON_BN_CLICKED(IDCANCEL, &CSocketTestClientDlg::OnBnClickedCancel) 

END_MESSAGE_MAP() 



// CSocketTestClientDlg message handlers 


BOOL CSocketTestClientDlg::OnInitDialog() 

{ 

CDialog::OnInitDialog(); 


// Add "About..." menu item to system menu. 


// IDM_ABOUTBOX must be in the system command range. 

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 

ASSERT(IDM_ABOUTBOX < 0xF000); 


CMenu* pSysMenu = GetSystemMenu(FALSE); 

if (pSysMenu != NULL) 

{ 

CString strAboutMenu; 

strAboutMenu.LoadString(IDS_ABOUTBOX); 

if (!strAboutMenu.IsEmpty()) 

{ 

pSysMenu->AppendMenu(MF_SEPARATOR); 

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 

} 

} 


// Set the icon for this dialog. The framework does this automatically 

// when the application's main window is not a dialog 

SetIcon(m_hIcon, TRUE); // Set big icon 

SetIcon(m_hIcon, FALSE); // Set small icon 


// TODO: Add extra initialization here 


return TRUE; // return TRUE unless you set the focus to a control 

} 


void CSocketTestClientDlg::OnSysCommand(UINT nID, LPARAM lParam) 

{ 

if ((nID & 0xFFF0) == IDM_ABOUTBOX) 

{ 

CAboutDlg dlgAbout; 

dlgAbout.DoModal(); 

} 

else 

{ 

CDialog::OnSysCommand(nID, lParam); 

} 

} 


// If you add a minimize button to your dialog, you will need the code below 

// to draw the icon. For MFC applications using the document/view model, 

// this is automatically done for you by the framework. 


void CSocketTestClientDlg::OnPaint() 

{ 

if (IsIconic()) 

{ 

CPaintDC dc(this); // device context for painting 


SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 


// Center icon in client rectangle 

int cxIcon = GetSystemMetrics(SM_CXICON); 

int cyIcon = GetSystemMetrics(SM_CYICON); 

CRect rect; 

GetClientRect(&rect); 

int x = (rect.Width() - cxIcon + 1) / 2; 

int y = (rect.Height() - cyIcon + 1) / 2; 


// Draw the icon 

dc.DrawIcon(x, y, m_hIcon); 

} 

else 

{ 

CDialog::OnPaint(); 

} 

} 


// The system calls this function to obtain the cursor to display while the user drags 

// the minimized window. 

HCURSOR CSocketTestClientDlg::OnQueryDragIcon() 

{ 

return static_cast<HCURSOR>(m_hIcon); 

} 



void CSocketTestClientDlg::OnBnClickedOk() 

{ 

UpdateData(TRUE); 


SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

if(s == -1) 

{ 

AfxMessageBox("Socket Initialiation Error"); 

} 

SOCKADDR_IN serveraddr; 

struct hostent *hostentry; 



bool bSent = false; 

std::string server = (const char*) m_udpserver; 

int portno = m_portno; 


hostentry = gethostbyname(server.c_str()); 

char *pipaddr = inet_ntoa (*(struct in_addr *)*hostentry->h_addr_list); 


memset(&serveraddr,0, sizeof(serveraddr)); 

serveraddr.sin_family = AF_INET; 

serveraddr.sin_port = htons(portno); 

serveraddr.sin_addr.s_addr = inet_addr(pipaddr); 


char sbuf[1024], rbuf[1024]; 

int len = sizeof(SOCKADDR_IN); 


UpdateData(TRUE); 

sprintf(sbuf,"%s\r\n", (const char*) m_senddata); 

if(sendto(s, sbuf, strlen(sbuf), 0,(SOCKADDR*)&serveraddr,len) == strlen(sbuf)) 

{ 

if(recvfrom(s, rbuf, 1024, 0, (SOCKADDR*)&serveraddr, &len) > 0) 

{ 

m_recvData = rbuf; 

UpdateData(FALSE); 

} 

} 

::closesocket(s); 

} 

 

 

테스트할 프로그램 UI

// SocketTestServerDlg.h : header file 

// 


#pragma once 



// CSocketTestServerDlg dialog 

class CSocketTestServerDlg : public CDialog 

{ 

// Construction 

public: 

CSocketTestServerDlg(CWnd* pParent = NULL); // standard constructor 


// Dialog Data 

enum { IDD = IDD_SOCKETTESTSERVER_DIALOG }; 


protected: 

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 



// Implementation 

public: 

void StartServer(); 

void ProcessClientRequest(); 

protected: 

bool m_bRefershData; 

SOCKET m_serversocket; 

HICON m_hIcon; 


// Generated message map functions 

virtual BOOL OnInitDialog(); 

afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 

afx_msg void OnPaint(); 

afx_msg HCURSOR OnQueryDragIcon(); 

afx_msg void OnTimer(UINT_PTR nIDEvent); 

DECLARE_MESSAGE_MAP() 

public: 

CString m_recvData; 

afx_msg void OnBnClickedOk(); 

afx_msg void OnBnClickedCancel(); 

}; 

 

테스트 UI CPP 내용

// SocketTestServerDlg.cpp : implementation file 

// 


#include "stdafx.h" 

#include "SocketTestServer.h" 

#include "SocketTestServerDlg.h" 

#include <process.h> 

#include <string> 

#include <sys/types.h> 


// CSocketTestServerDlg dialog 





CSocketTestServerDlg::CSocketTestServerDlg(CWnd* pParent /*=NULL*/) 

: CDialog(CSocketTestServerDlg::IDD, pParent) 

, m_recvData(_T("")) 

{ 

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 

} 


void CSocketTestServerDlg::DoDataExchange(CDataExchange* pDX) 

{ 

CDialog::DoDataExchange(pDX); 

DDX_Text(pDX, IDC_EDIT1, m_recvData); 

} 


BEGIN_MESSAGE_MAP(CSocketTestServerDlg, CDialog) 

ON_WM_SYSCOMMAND() 

ON_WM_PAINT() 

ON_WM_QUERYDRAGICON() 

//}}AFX_MSG_MAP 

ON_BN_CLICKED(IDOK, &CSocketTestServerDlg::OnBnClickedOk) 

ON_WM_TIMER() 

ON_BN_CLICKED(IDCANCEL, &CSocketTestServerDlg::OnBnClickedCancel) 

END_MESSAGE_MAP() 



// CSocketTestServerDlg message handlers 


BOOL CSocketTestServerDlg::OnInitDialog() 

{ 

CDialog::OnInitDialog(); 


// Add "About..." menu item to system menu. 


// IDM_ABOUTBOX must be in the system command range. 

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 

ASSERT(IDM_ABOUTBOX < 0xF000); 


CMenu* pSysMenu = GetSystemMenu(FALSE); 

if (pSysMenu != NULL) 

{ 

CString strAboutMenu; 

strAboutMenu.LoadString(IDS_ABOUTBOX); 

if (!strAboutMenu.IsEmpty()) 

{ 

pSysMenu->AppendMenu(MF_SEPARATOR); 

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 

} 

} 


// Set the icon for this dialog. The framework does this automatically 

// when the application's main window is not a dialog 

SetIcon(m_hIcon, TRUE); // Set big icon 

SetIcon(m_hIcon, FALSE); // Set small icon 


StartServer(); 

return TRUE; // return TRUE unless you set the focus to a control 

} 


void CSocketTestServerDlg::OnSysCommand(UINT nID, LPARAM lParam) 

{ 

if ((nID & 0xFFF0) == IDM_ABOUTBOX) 

{ 

CAboutDlg dlgAbout; 

dlgAbout.DoModal(); 

} 

else 

{ 

CDialog::OnSysCommand(nID, lParam); 

} 

} 


// If you add a minimize button to your dialog, you will need the code below 

// to draw the icon. For MFC applications using the document/view model, 

// this is automatically done for you by the framework. 


void CSocketTestServerDlg::OnPaint() 

{ 

if (IsIconic()) 

{ 

CPaintDC dc(this); // device context for painting 


SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); 


// Center icon in client rectangle 

int cxIcon = GetSystemMetrics(SM_CXICON); 

int cyIcon = GetSystemMetrics(SM_CYICON); 

CRect rect; 

GetClientRect(&rect); 

int x = (rect.Width() - cxIcon + 1) / 2; 

int y = (rect.Height() - cyIcon + 1) / 2; 


// Draw the icon 

dc.DrawIcon(x, y, m_hIcon); 

} 

else 

{ 

CDialog::OnPaint(); 

} 

} 


// The system calls this function to obtain the cursor to display while the user drags 

// the minimized window. 

HCURSOR CSocketTestServerDlg::OnQueryDragIcon() 

{ 

return static_cast<HCURSOR>(m_hIcon); 

} 



void CSocketTestServerDlg::StartServer() 

{ 

SOCKADDR_IN serveraddr; 

int portno = 1819; 

memset(&serveraddr,0, sizeof(serveraddr)); 

serveraddr.sin_family = AF_INET; 

serveraddr.sin_port = htons(portno); 

serveraddr.sin_addr.s_addr = INADDR_ANY; 


m_serversocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

if(m_serversocket == -1) 

{ 

AfxMessageBox("Socket Initialiation Error"); 

} 


if(bind(m_serversocket, (SOCKADDR*)&serveraddr,sizeof(SOCKADDR_IN)) < 0) 

{ 

AfxMessageBox("ERROR binding in the server socket"); 

exit(1); 

} 


SetTimer(0x01, 100, NULL); 

} 


static void f(void *p) 

{ 

CSocketTestServerDlg *pDlg = reinterpret_cast<CSocketTestServerDlg*>(p); 

pDlg->ProcessClientRequest(); 

} 


void CSocketTestServerDlg::ProcessClientRequest() 

{ 

SOCKADDR_IN clientaddr; 

struct hostent *hostentry; 

int len = sizeof(clientaddr); 


char rbuf[1024]; 

if( recvfrom(m_serversocket, rbuf, 1024, 0, (sockaddr*)&clientaddr, &len) > 0) 

{ 

for(int i = 1024; i >= 1; i--) 

{ 

if(rbuf[i] == '\n' && rbuf[i - 1] == '\r') 

{ 

rbuf[i-1] = '\0'; 

break; 

} 

} 

CString strRecvData; 


int portno = ntohs(clientaddr.sin_port); 

char *p = ::inet_ntoa(clientaddr.sin_addr); 

strRecvData.Format("%s\r\nClient: %s Port: %d\r\n%s\r\n\r\n", (const char*)CTime::GetCurrentTime().Format("%B %d, %Y %H:%M:%S"), p, portno, rbuf); 

m_recvData += strRecvData; 

m_bRefershData = true; 

strcat(rbuf, "\r\n"); 

sendto(m_serversocket, rbuf, 1024, 0, (sockaddr*)&clientaddr, len); 

} 

} 


void CSocketTestServerDlg::OnTimer(UINT_PTR nIDEvent) 

{ 

int idx = nIDEvent; 


if(m_bRefershData == true) 

{ 

m_bRefershData = false; 

UpdateData(FALSE); 

} 


fd_set fds; 

struct timeval timeout; 

int result; 

timeout.tv_sec = 0; 

timeout.tv_usec = 100; 


FD_ZERO(&fds); 

FD_SET(m_serversocket, &fds); 


int rc = select(sizeof(fds)*8, &fds, NULL, NULL, &timeout); 

if (rc==-1) 

{ 

AfxMessageBox("ERROR selecting in the server socket"); 

return; 

} 

else if(rc > 0) 

{ 

if (FD_ISSET(m_serversocket, &fds)) 

{ 

m_bRefershData = false; 

HANDLE h = (HANDLE) ::_beginthread(f, 0, (void*) this); 

} 


} 

CDialog::OnTimer(nIDEvent); 

} 

728x90
반응형

'프로그래밍 > MFC' 카테고리의 다른 글

BMP 저장  (0) 2020.11.12
Socket Error Code  (0) 2020.11.12
소켓 통신 Server 부분  (0) 2020.11.04
소켓 통신 Client 부분  (0) 2020.11.04
MFC DLL 배포 방법  (0) 2020.11.02