TCP服务器
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib") //包含静态库
/*
.obj + .lib 文件 组合打包成 .exe
*/
int main()
{
//1.加载套接字库
//第一个参数:版本
WORD wVersionRequseted=MAKEWORD(2,2);//低位字节:主版本,高位字节:次版本
//第二个参数:
WSADATA wd;
if (0 != WSAStartup(wVersionRequseted, &wd))
{
printf("加载套接字失败!错误代号:%d\n", GetLastError());
return 0;
}
//2.判断实际加载的版本
if (LOBYTE(wd.wVersion) != 2 || HIBYTE(wd.wVersion) != 2)
{
printf("加载套接字版本不一致!错误代号:%d\n", GetLastError());
return 0;
}
//3.创建套接字
//第一个参数:地址簇 IPV4
//第二个参数:套接字类型,流式套接字( SOCK_STREAM->TCP) 数据报套接字(SOCK_DGRAM->UDP)
//第三个参数:待定协议
SOCKET sockServer=socket(AF_INET, SOCK_STREAM, 0);
//4.设置套接字地址簇
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;//地址簇
addrSrv.sin_addr.S_un.S_addr =htonl(INADDR_ANY);//设置网卡 htonl:主机字节顺序转换为网络字节顺序
addrSrv.sin_port =htons(2020);//端口号范围 0 -> 65535 0:不取 1->1024 系统服务器 , 1024以上端口自己用
//SOCKADDR_IN==sockaddr_in
//5.绑定
if (SOCKET_ERROR == bind(sockServer, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))//绑定套接字,套接字地址簇,大小
{
printf("绑定失败!错误代号:%d\n", WSAGetLastError());
return 0;
}
//6.将套接字设置为监听模式
//第一个参数:套接字
//第二个参数:挂起连接的队列的最大长度
if (SOCKET_ERROR == listen(sockServer, 5))
{
printf("监听失败!错误代号:%d\n", WSAGetLastError());
return 0;
}
//7.等待客户端连接请求
SOCKADDR_IN addrClient;
int length = sizeof(SOCKADDR);
while (1)
{
SOCKET clientSocket=accept(sockServer, (SOCKADDR*)&addrClient, &length);
//inet_ntoa() 是一个用于将 IPv4 地址从网络字节序转换为点分十进制字符串表示的函数
//ntohl 网络字节顺序转换成主机字节顺序
printf("客户端:%s:%d连接服务器\n", inet_ntoa(addrClient.sin_addr),addrClient.sin_port);
//接收信息
//第一个参数:套接字
//第二个参数:发送的缓冲区
//第三个参数:缓冲区大小
char szRecvBuf[100] = { 0 };
recv(clientSocket, szRecvBuf, sizeof(szRecvBuf), 0);
printf("客户端说:%s\n", szRecvBuf);
//发送信息
char szSenBuf[100] = "客户端,hello";
send(clientSocket, szSenBuf, strlen(szSenBuf) + 1, 0);
//关闭套接字
closesocket(clientSocket);
}
//8.关闭套接字
closesocket(sockServer);
//9.清理库
WSACleanup();
return 0;
}
TCP客户端
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib") //包含静态库
/*
.obj + .lib 文件 组合打包成 .exe
*/
int main()
{
char szServerIPAddress[16];
printf("请输入需要连接的服务器IP地址:\n");
scanf("%s",szServerIPAddress);
//1.加载套接字库
//第一个参数:版本
WORD wVersionRequseted = MAKEWORD(2, 2);//低位字节:主版本,高位字节:次版本
//第二个参数:
WSADATA wd;
if (0 != WSAStartup(wVersionRequseted, &wd))
{
printf("加载套接字失败!错误代号:%d\n", GetLastError());
return 0;
}
//2.判断实际加载的版本
if (LOBYTE(wd.wVersion) != 2 || HIBYTE(wd.wVersion) != 2)
{
printf("加载套接字版本不一致!错误代号:%d\n", GetLastError());
return 0;
}
//3.创建套接字
//第一个参数:地址簇 IPV4
//第二个参数:套接字类型,流式套接字( SOCK_STREAM->TCP) 数据报套接字(SOCK_DGRAM->UDP)
//第三个参数:待定协议
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
//4.连接服务器
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;//地址簇
addrSrv.sin_addr.S_un.S_addr = inet_addr(szServerIPAddress);
addrSrv.sin_port = htons(2020);
if (connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
{
printf("连接服务器失败.错误代号:%d\n",WSAGetLastError());
return 0;
}
printf("连接服务器成功!\n");
//5.发送信息
char szSendBuf[100] = "服务器,hello";
send(sockClient, szSendBuf, strlen(szSendBuf) + 1,0);
//接收信息
//第一个参数:套接字
//第二个参数:发送的缓冲区
//第三个参数:缓冲区大小
char szRecvBuf[100] = { 0 };
recv(sockClient, szRecvBuf, sizeof(szRecvBuf), 0);
printf("服务器说:%s\n", szRecvBuf);
//7.关闭套接字
closesocket(sockClient);
//8.清理库
WSACleanup();
return 0;
}
有错误代码可以进行查找
将错误代码输入
UDP 服务器
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib") //包含静态库
/*
.obj + .lib 文件 组合打包成 .exe
*/
int main()
{
//1.加载套接字库
//第一个参数:版本
WORD wVersionRequseted = MAKEWORD(2, 2);//低位字节:主版本,高位字节:次版本
//第二个参数:
WSADATA wd;
if (0 != WSAStartup(wVersionRequseted, &wd))
{
printf("加载套接字失败!错误代号:%d\n", GetLastError());
return 0;
}
//2.判断实际加载的版本
if (LOBYTE(wd.wVersion) != 2 || HIBYTE(wd.wVersion) != 2)
{
printf("加载套接字版本不一致!错误代号:%d\n", GetLastError());
return 0;
}
//3.创建套接字
//第一个参数:地址簇 IPV4
//第二个参数:套接字类型,流式套接字( SOCK_STREAM->TCP) 数据报套接字(SOCK_DGRAM->UDP)
//第三个参数:待定协议
SOCKET sockServer = socket(AF_INET, SOCK_DGRAM, 0);
//4.设置套接字地址簇
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;//地址簇
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//设置网卡 htonl:主机字节顺序转换为网络字节顺序
addrSrv.sin_port = htons(2021);//端口号范围 0 -> 65535 0:不取 1->1024 系统服务器 , 1024以上端口自己用
//SOCKADDR_IN==sockaddr_in
//5.绑定
if (SOCKET_ERROR == bind(sockServer, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))//绑定套接字,套接字地址簇,大小
{
printf("绑定失败!错误代号:%d\n", WSAGetLastError());
return 0;
}
//6.接收消息
SOCKADDR_IN addrclient;
int length = sizeof(SOCKADDR);
char szRecvBuf[100];
recvfrom(sockServer, szRecvBuf, sizeof(szRecvBuf), 0,(SOCKADDR*)&addrclient,&length);
printf("客户端:%s\n", szRecvBuf);
//发送
char szSendBuf[100] = "客户端你好!";
sendto(sockServer, szSendBuf,strlen(szSendBuf)+1,0, (SOCKADDR*)&addrclient,sizeof(SOCKADDR));
//7.关闭套接字
closesocket(sockServer);
//8.清理库
WSACleanup();
return 0;
}
UDP客户端
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib") //包含静态库
/*
.obj + .lib 文件 组合打包成 .exe
*/
int main()
{
char szServerIPAddress[16];
printf("请输入需要连接的服务器IP地址:\n");
scanf("%s", szServerIPAddress);
//1.加载套接字库
//第一个参数:版本
WORD wVersionRequseted = MAKEWORD(2, 2);//低位字节:主版本,高位字节:次版本
//第二个参数:
WSADATA wd;
if (0 != WSAStartup(wVersionRequseted, &wd))
{
printf("加载套接字失败!错误代号:%d\n", GetLastError());
return 0;
}
//2.判断实际加载的版本
if (LOBYTE(wd.wVersion) != 2 || HIBYTE(wd.wVersion) != 2)
{
printf("加载套接字版本不一致!错误代号:%d\n", GetLastError());
return 0;
}
//3.创建套接字
//第一个参数:地址簇 IPV4
//第二个参数:套接字类型,流式套接字( SOCK_STREAM->TCP) 数据报套接字(SOCK_DGRAM->UDP)
//第三个参数:待定协议
SOCKET sockServer = socket(AF_INET, SOCK_DGRAM, 0);
//4.发送消息
SOCKADDR_IN addrServer;
addrServer.sin_addr.S_un.S_addr = inet_addr(szServerIPAddress);
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(2021);
int length = sizeof(SOCKADDR);
char szSendBuf[100]="服务器你好!";
sendto(sockServer, szSendBuf, sizeof(szSendBuf), 0, (SOCKADDR*)&addrServer,sizeof(SOCKADDR));
//6.接收消息
SOCKADDR_IN addrclient;
length = sizeof(SOCKADDR);
char szRecvBuf[100];
recvfrom(sockServer, szRecvBuf, sizeof(szRecvBuf), 0, (SOCKADDR*)&addrclient, &length);
printf("服务器:%s\n", szRecvBuf);
//7.关闭套接字
closesocket(sockServer);
//8.清理库
WSACleanup();
return 0;
}
MFC TCP通信
勾选高级功能
如果没有勾选
TCP服务器
ui 设置
添加套接字类
创建虚函数接收连接
在服务器里面创建客户端类
在客户端类中添加接收的响应函数
断开连接
// TCPChatServerDlg.h: 头文件
//
#pragma once
//类的前置声明
class ClistenSocket;
// CTCPChatServerDlg 对话框
class CTCPChatServerDlg : public CDialogEx
{
// 构造
public:
CTCPChatServerDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TCPCHATSERVER_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
ClistenSocket* m_plistSocket;
afx_msg void OnBnClickedBtnStart();
afx_msg void OnBnClickedBtnClose();
CListCtrl m_list;
};
// TCPChatServerDlg.cpp: 实现文件
//
#include "pch.h"
#include "framework.h"
#include "TCPChatServer.h"
#include "TCPChatServerDlg.h"
#include "afxdialogex.h"
#include "ClistenSocket.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define PORT 2020 //端口号
// CTCPChatServerDlg 对话框
CTCPChatServerDlg::CTCPChatServerDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_TCPCHATSERVER_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_plistSocket = NULL;
}
void CTCPChatServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, m_list);
}
BEGIN_MESSAGE_MAP(CTCPChatServerDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_START, &CTCPChatServerDlg::OnBnClickedBtnStart)
ON_BN_CLICKED(IDC_BTN_CLOSE, &CTCPChatServerDlg::OnBnClickedBtnClose)
END_MESSAGE_MAP()
// CTCPChatServerDlg 消息处理程序
BOOL CTCPChatServerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
m_list.InsertColumn(0,L"IP地址",LVCFMT_LEFT,150);
m_list.InsertColumn(1, L"端口号", LVCFMT_LEFT,80);
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CTCPChatServerDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CTCPChatServerDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CTCPChatServerDlg::OnBnClickedBtnStart()
{
CString strMsg;
m_plistSocket = new ClistenSocket;
//创建套接字
//第一个参数:端口号
//第二个参数:套接字类型 TCP->SOCK_STREAM ,UDP->SOCK_DGRAM
//后前面全是默认参数
if (FALSE==m_plistSocket->Create(PORT, SOCK_STREAM))
{
strMsg.Format(L"开启服务器失败.错误代号:%d",GetLastError());
MessageBox(strMsg, L"提示");
return;
}
//将套接字设置为监听模式
if (FALSE == m_plistSocket->Listen())
{
strMsg.Format(L"开启服务器失败.错误代号:%d", GetLastError());
MessageBox(strMsg, L"提示");
return;
}
//禁用按钮
GetDlgItem(IDC_BTN_START)->EnableWindow(FALSE);
GetDlgItem(IDC_BTN_CLOSE)->EnableWindow(TRUE);
}
void CTCPChatServerDlg::OnBnClickedBtnClose()
{
if (m_plistSocket)
{
m_plistSocket->Close();
delete m_plistSocket;
m_plistSocket = NULL;
//禁用按钮
GetDlgItem(IDC_BTN_START)->EnableWindow(TRUE);
GetDlgItem(IDC_BTN_CLOSE)->EnableWindow(FALSE);
}
}
//ClistenSocket.h
#pragma once
#include <afxsock.h>
class ClistenSocket :public CSocket
{
public:
ClistenSocket();
~ClistenSocket();
virtual void OnAccept(int nErrorCode);
};
//ClistenSocket.cpp
#include "pch.h"
#include "ClistenSocket.h"
#include "CClientSocket.h"
#include "TCPChatServerDlg.h"
#include "TCPChatServer.h"
ClistenSocket::ClistenSocket()
{
}
ClistenSocket::~ClistenSocket()
{
}
//监听到
void ClistenSocket::OnAccept(int nErrorCode)
{
CClientSocket *pSocket = new CClientSocket;
//第一个参数:连接的新的套接字,其他参数为默认
Accept(*pSocket);
CString strIPAddress;
UINT uPort;
//获取IP地址
pSocket->GetPeerName(strIPAddress, uPort);
//保存客户端套接字指针对象
((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.push_back(pSocket);
//获取主对话框中的UI
CTCPChatServerDlg* pMainDlg=(CTCPChatServerDlg*)AfxGetMainWnd();
//插入到列表中
int nCount = pMainDlg->m_list.GetItemCount();//获取插入行数
pMainDlg->m_list.InsertItem(nCount, strIPAddress);
CString str;
str.Format(L"%d", uPort);
pMainDlg->m_list.SetItemText(nCount,1,str);//插入端口号
str.Format(L"客户端%s:%d上线了\r\n",strIPAddress,uPort);
//转发给所有客户端
//((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.push_back(pSocket);
std::list<CClientSocket*>::iterator it;
for (it = ((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.begin(); it != ((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.end(); ++it)
{
CClientSocket* pSocket = *it;
//发送
pSocket->Send(str, str.GetLength() * 2);//长度*2 ==字节数
}
CSocket::OnAccept(nErrorCode);
}
//CClientSocket.h
#pragma once
#include <afxsock.h>
class CClientSocket :public CSocket
{
public:
CClientSocket();
~CClientSocket();
virtual void OnReceive(int nErrorCode);
virtual void OnClose(int nErrorCode);
};
//CClientSocket.cpp
#include "pch.h"
#include "CClientSocket.h"
#include "TCPChatServer.h"
#include "TCPChatServerDlg.h"
CClientSocket::CClientSocket()
{
}
CClientSocket::~CClientSocket()
{
}
//接收
void CClientSocket::OnReceive(int nErrorCode)
{
wchar_t szRecvBuf[512];
ZeroMemory(szRecvBuf, sizeof(szRecvBuf));//清空内存,防止没有字符串终止符出现乱码
//接收数据
//第一个参数:缓存
//第二个参数:缓存大小
int n=Receive(szRecvBuf, sizeof(szRecvBuf));//n为实际接收多少字节
//AfxMessageBox(szRecvBuf);
//获取当前时间
CTime time = CTime::GetCurrentTime();
CString strIPAddress;
UINT uPort;
GetPeerName(strIPAddress,uPort);//获取IP地址和端口号
CString str;
str.Format(L"%s:%d\t%s\r\n%s\r\n", strIPAddress, uPort,time.Format(L"%H:%M:%S"), szRecvBuf);
//转发给所有客户端
//((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.push_back(pSocket);
std::list<CClientSocket*>::iterator it;
for (it = ((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.begin(); it != ((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.end(); ++it)
{
CClientSocket* pSocket = *it;
//发送
pSocket->Send(str, str.GetLength() * 2);//长度*2 ==字节数
}
CSocket::OnReceive(nErrorCode);
}
void CClientSocket::OnClose(int nErrorCode)
{
CString strIPAddress;
UINT uPort;
GetPeerName(strIPAddress, uPort);//获取IP地址和端口号
//删除链表中的IP地址信息
CTCPChatServerDlg* pMainDlg = (CTCPChatServerDlg*)AfxGetMainWnd();
int nCount = pMainDlg->m_list.GetItemCount();//获取总行数
for (int i = 0; i < nCount; i++)
{
//判断IP地址和端口号是否和链表中数据一致
if (pMainDlg->m_list.GetItemText(i, 0) == strIPAddress && _wtoi(pMainDlg->m_list.GetItemText(i, 1)) == uPort)
{
pMainDlg->m_list.DeleteItem(i);
break;
}
}
//从list释放内存
std::list<CClientSocket*>::iterator it;
for (it = ((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.begin(); it != ((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.end(); ++it)
{
CClientSocket* pSocket = *it;
if (pSocket == this)
{
((CTCPChatServerApp*)AfxGetApp())->m_Clientlist.erase(it);
delete pSocket;
break;
}
}
CSocket::OnClose(nErrorCode);
}
TCP 客户端
ui 设置
客户端类
接受响应函数
// TCPChatClientDlg.h: 头文件
//
#pragma once
class CClientSocket;
// CTCPChatClientDlg 对话框
class CTCPChatClientDlg : public CDialogEx
{
// 构造
public:
CTCPChatClientDlg(CWnd* pParent = nullptr); // 标准构造函数
~CTCPChatClientDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TCPCHATCLIENT_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CString m_strSendMsg;
CClientSocket* m_pClientSocket;
afx_msg void OnBnClickedBtnSend();
afx_msg void OnBnClickedBtnClose();
CEdit m_edit;
void ShowMessage(CString strMsg);
};
// TCPChatClientDlg.cpp: 实现文件
//
#include "pch.h"
#include "framework.h"
#include "TCPChatClient.h"
#include "TCPChatClientDlg.h"
#include "afxdialogex.h"
#include "CClientSocket.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define PORT 2020
// CTCPChatClientDlg 对话框
CTCPChatClientDlg::CTCPChatClientDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_TCPCHATCLIENT_DIALOG, pParent)
, m_strSendMsg(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pClientSocket = NULL;
}
CTCPChatClientDlg::~CTCPChatClientDlg()
{
if (m_pClientSocket)
{
delete m_pClientSocket;
m_pClientSocket = NULL;
}
}
void CTCPChatClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT2, m_strSendMsg);
DDX_Control(pDX, IDC_EDIT1, m_edit);
}
BEGIN_MESSAGE_MAP(CTCPChatClientDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_SEND, &CTCPChatClientDlg::OnBnClickedBtnSend)
ON_BN_CLICKED(IDC_BTN_CLOSE, &CTCPChatClientDlg::OnBnClickedBtnClose)
END_MESSAGE_MAP()
// CTCPChatClientDlg 消息处理程序
BOOL CTCPChatClientDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
CString strMsg;
m_pClientSocket = new CClientSocket;
if (FALSE == m_pClientSocket->Create())//默认为TCP协议
{
strMsg.Format(L"初始化网络失败.错误代号:%d", GetLastError());
MessageBox(strMsg, L"提示");
//结束对话框
EndDialog(IDOK);
}
//连接服务器
if (FALSE==m_pClientSocket->Connect(L"192.168.1.109", PORT))
{
strMsg.Format(L"连接服务器失败.错误代号:%d", GetLastError());
MessageBox(strMsg, L"提示");
//结束对话框
EndDialog(IDOK);
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CTCPChatClientDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CTCPChatClientDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
//发送
void CTCPChatClientDlg::OnBnClickedBtnSend()
{
UpdateData(TRUE);
if (m_strSendMsg.IsEmpty())
{
MessageBox(L"发消息为空");
return;
}
if (m_strSendMsg.GetLength() > 512)
{
MessageBox(L"发送内容太多");
return;
}
//发消息
//第一个参数:发送的消息
//第二个参数:发送的长度
int n=m_pClientSocket->Send(m_strSendMsg,m_strSendMsg.GetLength()*2);
}
//关闭
void CTCPChatClientDlg::OnBnClickedBtnClose()
{
EndDialog(IDOK);
}
//显示消息
void CTCPChatClientDlg::ShowMessage(CString strMsg)
{
//获取原来字符的长度
int nLength = m_edit.GetWindowTextLength();
m_edit.SetSel(nLength, -1);//设置光标位置
//追加
strMsg = strMsg + L"\r\n";
m_edit.ReplaceSel(strMsg);//设置文本字符串
}
//CClientSocket.h
#pragma once
#include <afxsock.h>
class CClientSocket :public CSocket
{
public:
CClientSocket();
~CClientSocket();
virtual void OnReceive(int nErrorCode);
};
//CClientSocket.cpp
#include "pch.h"
#include "CClientSocket.h"
#include "TCPChatClientDlg.h"
CClientSocket::CClientSocket()
{
}
CClientSocket::~CClientSocket()
{
}
void CClientSocket::OnReceive(int nErrorCode)
{
wchar_t szRecvBuf[512];
ZeroMemory(szRecvBuf, sizeof(szRecvBuf));//清空内存,防止没有字符串终止符出现乱码
//接收数据
//第一个参数:缓存
//第二个参数:缓存大小
int n = Receive(szRecvBuf, sizeof(szRecvBuf));//n为实际接收多少字节
//显示到界面
//获取到控件
CTCPChatClientDlg* pMainDlg=(CTCPChatClientDlg*)AfxGetMainWnd();
pMainDlg->ShowMessage(szRecvBuf);
CSocket::OnReceive(nErrorCode);
}
MFC UDP通信
ui 设置
添加关联变量
> 添加类
// UDPChatDlg.h: 头文件
//
#pragma once
#include "CClientSocket.h"
// CUDPChatDlg 对话框
class CUDPChatDlg : public CDialogEx
{
// 构造
public:
CUDPChatDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_UDPCHAT_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CIPAddressCtrl m_IPAddressCtrl;
int m_uPort;
CEdit m_edit;
CString m_strSendMsg;
afx_msg void OnBnClickedBtnSend();
CClientSocket m_socket;
void ShowMessage(CString strMsg);
int m_uMyPort;
afx_msg void OnBnClickedBtnCreate();
};
// UDPChatDlg.cpp: 实现文件
//
#include "pch.h"
#include "framework.h"
#include "UDPChat.h"
#include "UDPChatDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CUDPChatDlg 对话框
CUDPChatDlg::CUDPChatDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_UDPCHAT_DIALOG, pParent)
, m_strSendMsg(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CUDPChatDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_IPADDRESS1, m_IPAddressCtrl);
DDX_Text(pDX, IDC_EDIT1, m_uPort);
DDX_Control(pDX, IDC_EDIT2, m_edit);
DDX_Text(pDX, IDC_EDIT3, m_strSendMsg);
DDX_Text(pDX, IDC_EDIT4, m_uMyPort);
}
BEGIN_MESSAGE_MAP(CUDPChatDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_SEND, &CUDPChatDlg::OnBnClickedBtnSend)
ON_BN_CLICKED(IDC_BTN_CREATE, &CUDPChatDlg::OnBnClickedBtnCreate)
END_MESSAGE_MAP()
// CUDPChatDlg 消息处理程序
BOOL CUDPChatDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CUDPChatDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CUDPChatDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
//发送
void CUDPChatDlg::OnBnClickedBtnSend()
{
UpdateData(TRUE);
if (m_strSendMsg.IsEmpty())
{
MessageBox(L"不能发送空消息");
return;
}
if (m_strSendMsg.GetLength() >= 512)
{
MessageBox(L"发送消息过长");
return;
}
CString strIPAddress;
m_IPAddressCtrl.GetWindowText(strIPAddress);
if (strIPAddress == L"0.0.0.0")
{
MessageBox(L"IP地址不能为空");
return;
}
m_socket.SendTo(m_strSendMsg, m_strSendMsg.GetLength() * 2, m_uPort,strIPAddress);
}
void CUDPChatDlg::ShowMessage(CString strMsg)
{
int nLength = m_edit.GetWindowTextLength();
m_edit.SetSel(nLength, -1);//设置光标位置
//追加
strMsg = strMsg + L"\r\n";
m_edit.ReplaceSel(strMsg);
}
void CUDPChatDlg::OnBnClickedBtnCreate()
{
UpdateData(TRUE);
CString str;
if (FALSE == m_socket.Create(m_uMyPort, SOCK_DGRAM))
{
str.Format(L"初始化网络失败,错误代号:%d", GetLastError());
MessageBox(str, L"提示");
EndDialog(IDOK);
return ;
}
}
//CClientSocket.h
#pragma once
#include <afxsock.h>
class CClientSocket :public CSocket
{
public:
CClientSocket();
~CClientSocket();
virtual void OnReceive(int nErrorCode);
};
//CClientSocket.cpp文章来源:https://www.toymoban.com/news/detail-619965.html
#include "pch.h"
#include "CClientSocket.h"
#include "UDPChatDlg.h"
CClientSocket::CClientSocket()
{
}
CClientSocket::~CClientSocket()
{
}
void CClientSocket::OnReceive(int nErrorCode)
{
wchar_t szRecvMsg[512];
ZeroMemory(szRecvMsg,sizeof(szRecvMsg));
//接收数据
CString strIPaddress;
UINT uPort;
ReceiveFrom(szRecvMsg,sizeof(szRecvMsg),strIPaddress,uPort);
//显示到界面
CUDPChatDlg* pMainDlg=(CUDPChatDlg*)AfxGetMainWnd();
pMainDlg->ShowMessage(szRecvMsg);
CSocket::OnReceive(nErrorCode);
}
文章来源地址https://www.toymoban.com/news/detail-619965.html
到了这里,关于18 MFC TCP和UDP 网络通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!