Download full source code on below link
Explore My Other Channel for More Cool and Valuable Insights
👉 Youtube Learn Tech Tips👉 Tiktok
👉 Facebook:In Computer science client-server is a software architecture model consisting of two parts, client systems and server systems, both communicating over a computer network or on the same computer. A client-server application is a distributed system made up of both client and server software.
Server, Client is one of advance tech skill for C++/MFC. So if you want to understand it clearly. Reading my source code, you can easy do it.
Code Server Side:
// ServerDlg.cpp : implementation file
// Last Modified: 21-12-2015
// ViLH / Zidane (huuvi168@gmail.com)
#include "stdafx.h"
#include "Server.h"
#include "ServerDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CServerDlg dialog
CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
: CDialog(CServerDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_TEXT, m_txtMessage);
DDX_Control(pDX, IDC_LIST_MESSAGE, m_lstMessage);
}
BEGIN_MESSAGE_MAP(CServerDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDCANCEL, &CServerDlg::OnBnClickedCancel)
ON_BN_CLICKED(IDC_BUTTON_SEND, &CServerDlg::OnBnClickedButtonSend)
END_MESSAGE_MAP()
// CServerDlg message handlers
BOOL CServerDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 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
// Thiết lập list control
m_lstMessage.InsertColumn(0, L"My Message");
m_lstMessage.SetColumnWidth(0, 300);
// số dòng ban đầu:
m_iRow = 0;
// giới hạn text, hàn chế tràn buffer
m_txtMessage.SetLimitText(100);
// size control listControl
m_cMySize.cx = 0;
m_cMySize.cy = 30;
// int num client connect (khởi tạo số lượng client đang connect)
for (int i=0; i<NUMCLIENT; i++)
m_sSockClient[i] = NULL;
// init winsock
WSAData wsa;
WORD dwVersion = MAKEWORD(2,1);
int iResult = WSAStartup(dwVersion, &wsa);
if (iResult != 0)
{
MessageBox(L"cannot start up win sock", L"Warning", MB_OK);
return TRUE;
}
m_saServer.sin_addr.s_addr = htonl(INADDR_ANY);
m_saServer.sin_family = AF_INET;
m_saServer.sin_port = htons(PORT);
m_ilen = sizeof(m_saServer);
m_sSock = socket(AF_INET, SOCK_STREAM, NULL);
if (bind(m_sSock, (SOCKADDR*)&m_saServer, m_ilen))
{
m_txtMessage.SetWindowText(L"Cannot bind ...");
return TRUE;
}
m_txtMessage.SetWindowText(L"Server listening ...");
listen(m_sSock, NUMCLIENT);
AfxBeginThread(&DoWork, 0);
return TRUE; // return TRUE unless you set the focus to a control
}
// 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 CServerDlg::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();
}
}
HCURSOR CServerDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CServerDlg::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
OnCancel();
}
// **************************************************************
UINT DoWork(LPVOID p)
{
CString sClientIPAddress;
CString sMessage;
CServerDlg *dlg = (CServerDlg*)AfxGetApp()->GetMainWnd();
// Get Total client is free
int iNum = dlg->GetClientCount();
// Get Data from client
int iData = 0;
// Is Exists client connected
if (iNum >= 0)
{
iData = 1;
dlg->m_sSockClient[iNum] =
accept( dlg->m_sSock, (sockaddr*) &(dlg->m_saServer), &(dlg->m_ilen) );
// Get IP from client connecting
sClientIPAddress = inet_ntoa(dlg->m_saServer.sin_addr);
// Cannot accept connect with client
if (dlg->m_sSockClient[iNum] == INVALID_SOCKET)
dlg->m_txtMessage.SetWindowText(L"Error Accept");
else
{
// Create Thread for every client
AfxBeginThread(&DoWork, 0);
sMessage.Append(L"IP: " + sClientIPAddress + L" Connected!");
sMessage.AppendFormat(L" - Num = %d", iNum);
dlg->m_lstMessage.InsertItem(dlg->m_iRow++, sMessage);
// scroll for view (cuộn thanh cuộn xuống cho dễ nhìn)
dlg->m_lstMessage.Scroll(dlg->m_cMySize);
// Receive data from another IP
char cbuff[101];
while (iData != SOCKET_ERROR)
{
memset(cbuff, 0x0, 101);
iData = recv(dlg->m_sSockClient[iNum], cbuff, 101, 0);
dlg->SetForegroundWindow();
sMessage = L"";
if (iData != SOCKET_ERROR)
{
// chèn câu chat vào list control
sMessage = cbuff;
dlg->m_lstMessage.InsertItem(dlg->m_iRow++, sMessage);
dlg->m_lstMessage.Scroll(dlg->m_cMySize);
dlg->SendMsgToAllClient(dlg->m_sSockClient[iNum], cbuff);
}
}
// client "disconnect" khi gặp lỗi .. / disconnect
sMessage.Append(L"Client: " + sClientIPAddress + L" Disconnected!");
dlg->m_lstMessage.InsertItem(dlg->m_iRow++, sMessage);
dlg->m_lstMessage.Scroll(dlg->m_cMySize);
dlg->ConvertToChar(sMessage, cbuff, 101);
dlg->SendMsgToAllClient(dlg->m_sSockClient[iNum], cbuff);
dlg->m_lstMessage.Scroll(dlg->m_cMySize);
dlg->m_sSockClient[iNum] = NULL;// release lại 1 kết nối
closesocket(dlg->m_sSockClient[iNum]);
}
}
AfxEndThread(0);
return 0;
}
// **************************************************************
// lấy số lượng toàn bộ client đang rãnh
int CServerDlg::GetClientCount(void)
{
for (int i=0; i<NUMCLIENT; i++)
{
if (m_sSockClient[i] == NULL)
return i;
}
return -1;
}
// **************************************************************
void CServerDlg::SendMsgToAllClient(SOCKET sock, char* message)
{
for (int i=0; i<NUMCLIENT; i++)
{
// Check send message to client.
// kiểm tra nếu tồn tại client và không phải chính bản thân thì send message
if (m_sSockClient[i] != NULL && m_sSockClient[i] != sock)
send (m_sSockClient[i],message, 101, 0);
}
}
// **************************************************************
// chuyển đổi CString to char*
char* CServerDlg::ConvertToChar(const CString& s, char* pAnsiString, int bufsize)
{
wcstombs(pAnsiString,(LPCTSTR) s, bufsize);
return pAnsiString;
}
// **************************************************************
// server disconnect: giải phóng ~>
CServerDlg::~CServerDlg()
{
for (int i = 0; i<NUMCLIENT; i++)
if (m_sSockClient[i] != NULL) // Client Exists (tồn tại client)
// chỉ send đến những client chưa disconnect
send (m_sSockClient[i], "Server Disconnected", 100, 0);
WSACleanup();
}
// **************************************************************
// Send Data with Button (Send dữ liệu tới client)
void CServerDlg::OnBnClickedButtonSend()
{
// TODO: Add your control notification handler code here
CString sMessage;
CString sAllMessage = L"Server: ";
m_txtMessage.GetWindowText(sMessage);
sAllMessage.Append(sMessage);
m_txtMessage.SetWindowText(L"");
m_lstMessage.InsertItem(m_iRow++ , sAllMessage);
// scroll theo size
m_lstMessage.Scroll(m_cMySize);
char buff[101];
ConvertToChar(sAllMessage, buff, 101);
for (int i=0; i<NUMCLIENT; i++)
if (m_sSockClient[i])
send(m_sSockClient[i], buff, 101, 0);
}
Code Client Side
// ClientDlg.cpp : implementation file
//
/*******************************************************
Author: VịLH / Zidane // huuvi168@gmail.com
*******************************************************/
#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CClientDlg dialog
CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
: CDialog(CClientDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_IPADDRESS, m_txtIPAddress);
DDX_Control(pDX, IDC_EDIT_MESSAGE, m_txtMessage);
DDX_Control(pDX, IDC_LIST_MESSAGE, m_lstMessage);
DDX_Control(pDX, IDC_EDIT_USERNAME, m_sName);
}
BEGIN_MESSAGE_MAP(CClientDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CClientDlg::OnBnClickedButtonConnect)
ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, &CClientDlg::OnBnClickedButtonDisconnect)
ON_BN_CLICKED(IDCANCEL, &CClientDlg::OnBnClickedCancel)
ON_BN_CLICKED(IDC_BUTTON_SEND, &CClientDlg::OnBnClickedButtonSend)
END_MESSAGE_MAP()
// CClientDlg message handlers
BOOL CClientDlg::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)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
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
// Settings default Value
m_iRow = 0;
m_txtIPAddress.SetWindowText(L"10.0.0.2");
m_txtMessage.SetLimitText(100);
m_lstMessage.InsertColumn(0, L"Client Message");
m_lstMessage.SetColumnWidth(0, 300);
m_cMySize.cx = 0;
m_cMySize.cy = 30;
// Name init
m_sName.SetWindowText(L"HuuVi");
m_bIsConnected = FALSE;
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(TRUE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CClientDlg::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 CClientDlg::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 CClientDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
// ************************************************************
void CClientDlg::OnBnClickedButtonConnect()
{
// TODO: Add your control notification handler code here
CString sAddress;
m_txtIPAddress.GetWindowText(sAddress);
char cAddress[50];
ConvertToChar(sAddress, cAddress, 50);
// Init winsock
WSAData wsa;
WORD dwVersion = MAKEWORD(2,1);
int iResult = WSAStartup(dwVersion, &wsa);
if (iResult != 0)
{
MessageBox(L"cannot start up win sock", L"Warning", MB_OK);
return;
}
m_saClient.sin_addr.s_addr = inet_addr(cAddress);
m_saClient.sin_family = AF_INET;
m_saClient.sin_port = htons(PORT);
m_sSock = socket(AF_INET, SOCK_STREAM, 0);
GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(FALSE);
m_bIsConnected = TRUE;
// AfxBeginThread(&DoWork, 0);
CreateThread(0,0,(LPTHREAD_START_ROUTINE)DoWork, (void *)0, 0, 0);
}
// **************************************************************
// Convert CString to char*
char* CClientDlg::ConvertToChar(const CString& s, char* pAnsiString, int bufsize)
{
wcstombs(pAnsiString,(LPCTSTR) s, bufsize);
return pAnsiString;
}
// **************************************************************
UINT DoWork(LPVOID p)
{
CClientDlg *dlg = (CClientDlg*)AfxGetApp()->GetMainWnd();
CString sAddress;
dlg->m_txtIPAddress.GetWindowText(sAddress);
// Connect to server ..
while ((connect(dlg->m_sSock,
(sockaddr*)&dlg->m_saClient, sizeof(dlg->m_saClient)) )
&& dlg->m_bIsConnected == TRUE)
{
dlg->m_txtMessage.SetWindowText(L"Please Wait ...");
char cbuf[50];
memset(cbuf, 0x0, NULL);
dlg->ConvertToChar(sAddress, cbuf, 50);
dlg->m_saClient.sin_addr.s_addr = inet_addr(cbuf);
}
CString sMessage;
CString sClientAddress;
char buff[101];
if (dlg->m_bIsConnected == TRUE) // connect succeed!
{
sClientAddress = inet_ntoa(dlg->m_saClient.sin_addr);
sMessage.Append(L"--> Client: " + sClientAddress + L" Connected!");
dlg->GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(TRUE);
dlg->m_lstMessage.InsertItem(dlg->m_iRow++, sMessage);
dlg->SetForegroundWindow();
int iData = 1; // Data receive from server and another client
// connect succeed and prepare receive data
while (iData != SOCKET_ERROR)
{
iData = recv(dlg->m_sSock, buff, 101, 0);
dlg->SetForegroundWindow();
if (iData != SOCKET_ERROR)
{
sMessage = buff;
dlg->m_lstMessage.InsertItem(dlg->m_iRow++, sMessage);
dlg->m_lstMessage.Scroll(dlg->m_cMySize);
}
if (dlg->m_bIsConnected == FALSE)
break;
}
}
sMessage = L"Client: " + sClientAddress + L" Disconnected!";
dlg->ConvertToChar(sMessage, buff, 101);
send (dlg->m_sSock, buff, 101, 0);
closesocket(dlg->m_sSock);
AfxEndThread(0);
return 0;
}
// ********************************************************
void CClientDlg::OnBnClickedButtonDisconnect()
{
// TODO: Add your control notification handler code here
m_bIsConnected = FALSE;
GetDlgItem(IDC_BUTTON_CONNECT)->EnableWindow(TRUE);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(FALSE);
CString sMessage = L"Disconnected";
m_lstMessage.InsertItem(m_iRow++, sMessage);
m_txtMessage.SetWindowText(L"");
closesocket(m_sSock);
}
// ********************************************************
// exit
void CClientDlg::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
OnCancel();
}
// ********************************************************
CClientDlg::~CClientDlg()
{
m_bIsConnected = FALSE;
closesocket(m_sSock);
}
// **************************************************************
void CClientDlg::OnBnClickedButtonSend()
{
// TODO: Add your control notification handler code here
CString sMessage;
CString sAllMessage;
m_sName.GetWindowText(sAllMessage);
m_txtMessage.GetWindowText(sMessage);
sAllMessage.Append(L":" + sMessage);
// Insert message into client
m_lstMessage.InsertItem(m_iRow++, sAllMessage);
m_lstMessage.Scroll(m_cMySize);
m_txtMessage.SetWindowText(L"");
char cbuff[101];
ConvertToChar(sAllMessage, cbuff, 101);
send (m_sSock, cbuff, 101, 0);
}
Are you interested in topic [Tips] Share free Source code about "Chat Application Using Server Client Architecture C++" from Webzone Tech Tips? If you have any thoughts or questions, please share them in the comment section below. I would love to hear from you and chat about it
Webzone Tech Tips Zidane