#pragma once
#include <WinSock2.h>
#pragma comment(lib, "WS2_32.lib")
#pragma warning(disable: 4996)
#define MAX_MESSAGE_LENGTH 1024
#define PORT 2000
class CListenSocket
{
public:
CListenSocket();
virtual ~CListenSocket();
static bool Init();
static bool Exit();
public:
void CloseClientSocket(SOCKET* pClientSocket);
BOOL InitListenSocket(HWND hWnd, UINT nPort);
SOCKET* AcceptClient(HWND hWnd);
SOCKET RecvMessages(char* pBuf, SOCKET* pClientSocket);
void SendMessages(const char* pBuf, SOCKET* pClientSocket = NULL);
UINT GetClientCount();
const BOOL IsConnected();
private:
void InitSockaddr();
void Prompt(HWND hWnd, const CString& str);
public:
CPtrList m_ClientList;
private:
sockaddr_in m_sockaddr;
SOCKET m_hSocket;
UINT m_nPort;
int m_nLength;
BOOL m_bConnected;
};
#include "pch.h"
#include "ListenSocket.h"
CListenSocket::CListenSocket() : m_bConnected(FALSE), m_hSocket(NULL), m_nLength(0), m_nPort(0)
{
Init();
memset(&m_sockaddr, 0, sizeof(sockaddr_in));
}
CListenSocket::~CListenSocket()
{
POSITION pNext = m_ClientList.GetHeadPosition();
while (pNext != NULL)
{
SOCKET* pItemSocket = reinterpret_cast<SOCKET*>(m_ClientList.GetNext(pNext));
CloseClientSocket(pItemSocket);
}
m_bConnected = FALSE;
m_ClientList.RemoveAll();
closesocket(m_hSocket);
Exit();
}
bool CListenSocket::Init()
{
WSADATA wsaData;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
OutputDebugString(CString(_T("WSAStartup failed with error")));
WSACleanup();
return false;
}
return true;
}
bool CListenSocket::Exit()
{
return WSACleanup();
}
const BOOL CListenSocket::IsConnected()
{
return m_bConnected;
}
UINT CListenSocket::GetClientCount()
{
UINT nCount = 0;
POSITION pNext = m_ClientList.GetHeadPosition();
while (pNext != NULL)
{
m_ClientList.GetNext(pNext);
nCount++;
}
return nCount;
}
void CListenSocket::Prompt(HWND hWnd, const CString& str)
{
MessageBox(hWnd, _bstr_t(CString(str)), _T("提示"), MB_OK | MB_ICONEXCLAMATION);
}
void CListenSocket::CloseClientSocket(SOCKET* pClientSocket)
{
POSITION pCurrent = NULL;
POSITION pNext = m_ClientList.GetHeadPosition();
if (pClientSocket == NULL)
return;
while (pNext != NULL)
{
pCurrent = pNext;
SOCKET* pItemSocket = reinterpret_cast<SOCKET*>(m_ClientList.GetNext(pNext));
if (*pItemSocket == *pClientSocket)
{
delete pItemSocket;
pItemSocket = NULL;
pClientSocket = NULL;
m_ClientList.RemoveAt(pCurrent);
return;
}
}
return;
}
void CListenSocket::InitSockaddr()
{
m_sockaddr.sin_family = AF_INET;
m_sockaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
m_sockaddr.sin_port = htons(m_nPort);
m_nLength = sizeof(sockaddr);
}
BOOL CListenSocket::InitListenSocket(HWND hWnd, UINT nPort)
{
m_nPort = nPort;
InitSockaddr();
m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
if (m_hSocket == INVALID_SOCKET)
{
Prompt(hWnd, _T("创建监听套接字失败"));
return FALSE;
}
int nRetVal = bind(m_hSocket, reinterpret_cast<const sockaddr*>(&m_sockaddr), m_nLength);
if (nRetVal == SOCKET_ERROR)
{
Prompt(hWnd, _T("绑定监听套接字失败"));
return FALSE;
}
nRetVal = listen(m_hSocket, SOMAXCONN);
if (nRetVal == SOCKET_ERROR)
{
Prompt(hWnd, _T("监听客户端失败"));
return FALSE;
}
return TRUE;
}
SOCKET* CListenSocket::AcceptClient(HWND hWnd)
{
SOCKET* pClientSocket = NULL;
SOCKET sAccept = accept(m_hSocket, reinterpret_cast<sockaddr*>(&m_sockaddr), &m_nLength);
if (sAccept == INVALID_SOCKET)
{
Prompt(hWnd, _T("接受客户端连接请求失败"));
return pClientSocket;
}
pClientSocket = new SOCKET(sAccept);
m_ClientList.AddTail(reinterpret_cast<void*>(pClientSocket));
m_bConnected = TRUE;
return pClientSocket;
}
SOCKET CListenSocket::RecvMessages(char* buf, SOCKET* pClientSocket)
{
return (recv(*pClientSocket, buf, MAX_MESSAGE_LENGTH, 0));
}
void CListenSocket::SendMessages(const char* pBuf, SOCKET* pClientSocket)
{
POSITION pNext = m_ClientList.GetHeadPosition();
while (pNext != NULL)
{
const SOCKET* pItemSocket = reinterpret_cast<const SOCKET*>(m_ClientList.GetNext(pNext));
if (pClientSocket == NULL)
{
send(*pItemSocket, pBuf, MAX_MESSAGE_LENGTH, 0);
}
else
{
if (*pItemSocket != *pClientSocket)
send(*pItemSocket, pBuf, MAX_MESSAGE_LENGTH, 0);
}
}
}
#pragma once
#include "ListenSocket.h"
class CMyServerDlg : public CDialogEx
{
public:
CMyServerDlg(CWnd* pParent = nullptr);
protected:
HICON m_hIcon;
virtual BOOL OnInitDialog();
afx_msg void OnBnClickedSendBtn();
DECLARE_MESSAGE_MAP()
public:
void StartListen();
void ChangeConnectionInfo();
static UINT ThreadProc(LPVOID lpParam);
private:
void InitAllContrls();
void SetConnectionStatus();
void SetConnectionNumber();
void SetSendBtnStatus();
void ShowMessages(const CString& str);
private:
CListenSocket m_mySocket;
};
#include "pch.h"
#include "framework.h"
#include "MyServer.h"
#include "MyServerDlg.h"
#include "afxdialogex.h"
CMyServerDlg::CMyServerDlg(CWnd* pParent )
: CDialogEx(IDD_MYSERVER_DIALOG, pParent)
, m_mySocket()
{
}
void CMyServerDlg::SetConnectionStatus()
{
if (m_mySocket.IsConnected() == FALSE)
{
SetDlgItemText(IDC_CONNECTION_STATIC, _T("服务器已开启"));
}
else
{
if (m_mySocket.m_ClientList.IsEmpty() == FALSE)
SetDlgItemText(IDC_CONNECTION_STATIC, _T("已有客户端连接到服务器"));
else
SetDlgItemText(IDC_CONNECTION_STATIC, _T("所有客户端断开与服务器的连接"));
}
}
void CMyServerDlg::SetConnectionNumber()
{
SetDlgItemInt(IDC_NUMBER_STATIC, m_mySocket.GetClientCount(), TRUE);
}
void CMyServerDlg::SetSendBtnStatus()
{
CButton* pBtn = reinterpret_cast<CButton*>(GetDlgItem(IDC_SEND_BTN));
if (TRUE == m_mySocket.m_ClientList.IsEmpty())
pBtn->EnableWindow(FALSE);
else
pBtn->EnableWindow(TRUE);
}
void CMyServerDlg::InitAllContrls()
{
CEdit* pEdit = reinterpret_cast<CEdit*>(GetDlgItem(IDC_SEND_EDIT));
pEdit->SetLimitText(MAX_MESSAGE_LENGTH);
SetSendBtnStatus();
SetConnectionStatus();
SetConnectionNumber();
}
void CMyServerDlg::StartListen()
{
if (m_mySocket.InitListenSocket(m_hWnd, PORT) == TRUE)
AfxBeginThread(&CMyServerDlg::ThreadProc, 0);
}
void CMyServerDlg::ChangeConnectionInfo()
{
SetConnectionStatus();
SetConnectionNumber();
SetSendBtnStatus();
}
UINT CMyServerDlg::ThreadProc(LPVOID lpParam)
{
char szMessages[MAX_MESSAGE_LENGTH];
memset(szMessages, 0, MAX_MESSAGE_LENGTH * sizeof(char));
SOCKET* pClientSocket = NULL;
SOCKET sRetValue = INVALID_SOCKET;
CMyServerDlg* pDlg = reinterpret_cast<CMyServerDlg*>(AfxGetApp()->GetMainWnd());
CListenSocket* pSocket = &pDlg->m_mySocket;
pClientSocket = pSocket->AcceptClient(pDlg->m_hWnd);
if (pClientSocket == NULL)
AfxEndThread(0);
pDlg->SetForegroundWindow();
pDlg->ChangeConnectionInfo();
AfxBeginThread(&CMyServerDlg::ThreadProc, 0);
do {
pDlg->SetForegroundWindow();
sRetValue = pSocket->RecvMessages(szMessages, pClientSocket);
if (sRetValue != SOCKET_ERROR && sRetValue != INVALID_SOCKET)
{
pDlg->ShowMessages(CString(szMessages));
pSocket->SendMessages(szMessages, pClientSocket);
}
} while (sRetValue != SOCKET_ERROR && sRetValue != INVALID_SOCKET);
pSocket->CloseClientSocket(pClientSocket);
pDlg->ChangeConnectionInfo();
AfxEndThread(0);
return 0;
}
void CMyServerDlg::ShowMessages(const CString& str)
{
CString strShow;
GetDlgItemText(IDC_SHOW_EDIT, strShow);
strShow += _T("\r\n");
strShow += str;
strShow.TrimLeft(_T("\r"));
SetDlgItemText(IDC_SHOW_EDIT, strShow);
CEdit* pShowEdit = reinterpret_cast<CEdit*>(GetDlgItem(IDC_SHOW_EDIT));
if (!pShowEdit) return;
pShowEdit->LineScroll(pShowEdit->GetLineCount());
}
BOOL CMyServerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
... ...
InitAllContrls();
StartListen();
return TRUE;
}
void CMyServerDlg::OnBnClickedSendBtn()
{
CString str;
GetDlgItemText(IDC_SEND_EDIT, str);
SetDlgItemText(IDC_SEND_EDIT, _T(""));
ShowMessages(str);
m_mySocket.SendMessages(_bstr_t(str));
}
#pragma once
#include <WinSock2.h>
#include <list>
#include <string>
using std::list;
using std::string;
#pragma comment(lib, "WS2_32.lib")
#pragma warning(disable: 4996)
#define MAX_MESSAGE_LENGTH 1024
#define PORT 2000
class CClientSocket
{
public:
CClientSocket(UINT nPort);
virtual ~CClientSocket();
static bool Init();
static bool Exit();
public:
BOOL CreateSocket(HWND hWnd);
BOOL Connect(HWND hWnd);
SOCKET Recv(char* pBuf);
void Send(const char* pBuf);
private:
void Prompt(HWND hWnd, const CString& str);
void GetIPAddress();
void InitSockAddr();
private:
SOCKET m_hSocket;
UINT m_nPort;
sockaddr_in m_sockaddr;
CString m_strHostName;
CString m_strIPAddr;
};
#include "pch.h"
#include "ClientSocket.h"
CClientSocket::CClientSocket(UINT nPort)
{
m_hSocket = NULL;
m_strHostName = _T("");
m_strIPAddr = _T("");
m_nPort = PORT;
InitSockAddr();
}
CClientSocket::~CClientSocket()
{
if (m_hSocket != NULL)
closesocket(m_hSocket);
m_hSocket = NULL;
}
bool CClientSocket::Init()
{
WSADATA wsaData;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
OutputDebugString(CString(_T("WSAStartup failed with error")));
WSACleanup();
return false;
}
return true;
}
bool CClientSocket::Exit()
{
return WSACleanup();
}
void CClientSocket::Prompt(HWND hWnd, const CString& str)
{
MessageBox(hWnd, _bstr_t(CString(str)), _T("提示"), MB_OK | MB_ICONEXCLAMATION);
}
void CClientSocket::GetIPAddress()
{
char szhostname[128];
memset(szhostname, 0, sizeof(szhostname) / sizeof(szhostname[0]));
CString strAddr;
int nRet = gethostname(szhostname, sizeof(szhostname) / sizeof(szhostname[0]));
if (nRet == 0)
{
m_strHostName = szhostname;
hostent* phost = gethostbyname(szhostname);
for (int j = 0; j < 4; j++)
{
if (j > 0)
m_strIPAddr += ".";
UCHAR* pAddr = (UCHAR*)(*phost->h_addr_list);
UINT uAddr = (UINT)pAddr[j];
strAddr.Format(_T("%u"), uAddr);
m_strIPAddr += strAddr;
}
}
}
void CClientSocket::InitSockAddr()
{
GetIPAddress();
m_sockaddr.sin_family = AF_INET;
m_sockaddr.sin_addr.S_un.S_addr = inet_addr(_bstr_t(m_strIPAddr));
m_sockaddr.sin_port = htons(m_nPort);
}
BOOL CClientSocket::CreateSocket(HWND hWnd)
{
SOCKET sRet = socket(AF_INET, SOCK_STREAM, 0);
if (sRet == INVALID_SOCKET)
{
Prompt(hWnd, _T("创建套接字失败"));
return FALSE;
}
m_hSocket = sRet;
return TRUE;
}
BOOL CClientSocket::Connect(HWND hWnd)
{
SOCKET sRet = connect(m_hSocket, (sockaddr*)&m_sockaddr, sizeof(sockaddr_in));
if (sRet == INVALID_SOCKET || sRet == SOCKET_ERROR)
{
Prompt(hWnd, _T("连接服务器失败"));
return FALSE;
}
return TRUE;
}
SOCKET CClientSocket::Recv(char* pBuf)
{
SOCKET sRet = recv(m_hSocket, pBuf, MAX_MESSAGE_LENGTH, 0);
CString str(pBuf);
OutputDebugString(str);
return sRet;
}
void CClientSocket::Send(const char* pBuf)
{
send(m_hSocket, pBuf, MAX_MESSAGE_LENGTH, 0);
}
#pragma once
class CClientSocket;
class CMyClientDlg : public CDialogEx
{
public:
CMyClientDlg(CWnd* pParent = nullptr);
virtual ~CMyClientDlg();
protected:
virtual BOOL OnInitDialog();
afx_msg void OnBnClickedConnectBtn();
afx_msg void OnBnClickedDisconnectBtn();
afx_msg void OnBnClickedSendBtn();
DECLARE_MESSAGE_MAP()
public:
void SetConnectionStatus(CString str);
void SetSendEditLimitText();
void SetBtnStatus(BOOL bEnable = FALSE);
void UpdateShowEdit(char* pBuf);
static UINT ThreadProc(LPVOID lpParam);
private:
CClientSocket* m_pClientSock;
};
CMyClientDlg::CMyClientDlg(CWnd* pParent )
: CDialogEx(IDD_MYCLIENT_DIALOG, pParent)
, m_pClientSock(NULL)
{
CClientSocket::Init();
}
CMyClientDlg::~CMyClientDlg()
{
if(m_pClientSock)
delete m_pClientSock;
CClientSocket::Exit();
}
void CMyClientDlg::SetConnectionStatus(CString str)
{
CStatic* pStatic = (CStatic*)GetDlgItem(IDC_STATUS_STATIC);
pStatic->SetWindowText((LPCTSTR)str);
}
void CMyClientDlg::SetSendEditLimitText()
{
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_SEND_EDIT);
pEdit->SetLimitText(MAX_MESSAGE_LENGTH);
}
void CMyClientDlg::SetBtnStatus(BOOL bEnable)
{
CButton* pBtnDisconnect = (CButton*)GetDlgItem(IDC_DISCONNECT_BTN);
CButton* pBtnConnect = (CButton*)GetDlgItem(IDC_CONNECT_BTN);
CButton* pBtnSend = (CButton*)GetDlgItem(IDC_SEND_BTN);
if (bEnable == FALSE)
{
pBtnConnect->EnableWindow(TRUE);
pBtnDisconnect->EnableWindow(FALSE);
pBtnSend->EnableWindow(FALSE);
}
else
{
pBtnConnect->EnableWindow(FALSE);
pBtnDisconnect->EnableWindow(TRUE);
pBtnSend->EnableWindow(TRUE);
}
}
void CMyClientDlg::UpdateShowEdit(char* pBuf)
{
CString strShow;
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_SHOW_EDIT);
if (!pEdit) return;
pEdit->GetWindowText(strShow);
strShow += _T("\r\n");
strShow += pBuf;
strShow.TrimLeft(_T("\r"));
pEdit->SetWindowText(strShow);
pEdit->LineScroll(pEdit->GetLineCount(), 0);
}
UINT CMyClientDlg::ThreadProc(LPVOID lpParam)
{
char buf[MAX_MESSAGE_LENGTH];
CMyClientDlg* pDlg = (CMyClientDlg*)AfxGetApp()->GetMainWnd();
SOCKET sRet = pDlg->m_pClientSock->Connect(pDlg->m_hWnd);
if (INVALID_SOCKET == sRet)
AfxEndThread(0);
pDlg->SetForegroundWindow();
pDlg->SetConnectionStatus(_T("已连接"));
pDlg->SetBtnStatus(TRUE);
do {
pDlg->SetForegroundWindow();
sRet = pDlg->m_pClientSock->Recv(buf);
if (SOCKET_ERROR != sRet || INVALID_SOCKET != sRet)
pDlg->UpdateShowEdit(buf);
} while (SOCKET_ERROR != sRet);
pDlg->SetConnectionStatus(_T("已断开"));
pDlg->SetBtnStatus(FALSE);
AfxEndThread(0);
return 0;
}
BOOL CMyClientDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
... ...
SetSendEditLimitText();
SetConnectionStatus(_T("未连接"));
SetBtnStatus(FALSE);
return TRUE;
}
void CMyClientDlg::OnBnClickedConnectBtn()
{
m_pClientSock = new CClientSocket(5530);
if (m_pClientSock->CreateSocket(m_hWnd) == FALSE)
return;
AfxBeginThread(&ThreadProc, NULL);
return;
}
void CMyClientDlg::OnBnClickedDisconnectBtn()
{
if (!m_pClientSock)
return;
m_pClientSock->~CClientSocket();
}
void CMyClientDlg::OnBnClickedSendBtn()
{
CString str;
CEdit* pEdit = (CEdit*)GetDlgItem(IDC_SEND_EDIT);
pEdit->GetWindowText(str);
pEdit->SetWindowText(_T(""));
UpdateShowEdit(_bstr_t(str));
m_pClientSock->Send(_bstr_t(str));
}