📄 tcpclient.cpp
字号:
/////////////////////////////////////////////////
// TCPClient.cpp文件
#include "TCPClient.h"
#include "resource.h"
//#include ".\tcpclient.h"
// 定义网络事件通知消息
#define WM_SOCKET WM_USER + 1
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
// 初始化Winsock库
WSADATA wsaData;
WORD sockVersion = MAKEWORD(2, 0);
::WSAStartup(sockVersion, &wsaData);
// 弹出主窗口对话框
CMainDialog dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
// 释放Winsock库
::WSACleanup();
return FALSE;
}
CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG, pParentWnd), m_ccb(_T(""))
{
}
void CMainDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_CBString(pDX, IDC_COMBO1, m_ccb);
DDX_CBString(pDX, IDC_COMBO2, m_ccb1);
DDX_CBString(pDX, IDC_COMBO3, m_ccb2);
DDX_CBString(pDX, IDC_COMBO4, m_ccb3);
DDX_CBString(pDX, IDC_COMBO5, m_ccb4);
DDX_CBString(pDX, IDC_EDIT_id, m_ccbid);
}
BEGIN_MESSAGE_MAP(CMainDialog, CDialog)
ON_BN_CLICKED(IDC_CONNECT, OnButtonConnect)
ON_BN_CLICKED(IDC_SEND, OnButtonSend)
ON_BN_CLICKED(IDC_CLEAR, OnButtonClear)
ON_MESSAGE(WM_SOCKET, OnSocket)
ON_BN_CLICKED(IDC_BUTTON_1, OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON_2, OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON_3, OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON_4, OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON_5, OnBnClickedButton5)
ON_BN_CLICKED(IDC_BUTTON_6, OnBnClickedButton6)
ON_BN_CLICKED(IDC_BUTTON_7, OnBnClickedButton7)
ON_BN_CLICKED(IDC_BUTTON_8, OnBnClickedButton8)
ON_BN_CLICKED(IDC_BUTTON_9, OnBnClickedButton9)
ON_BN_CLICKED(IDC_1, OnBnClicked1)
ON_BN_CLICKED(IDC_2, OnBnClicked2)
ON_BN_CLICKED(IDC_3, OnBnClicked3)
ON_BN_CLICKED(IDC_4, OnBnClicked4)
ON_BN_CLICKED(IDC_SENDFILE, OnBnClickedSendfile)
ON_BN_CLICKED(IDC_RECVFILE, OnBnClickedRecvfile)
ON_EN_CHANGE(IDC_EDIT_showpicture, OnEnChangeEditshowpicture)
END_MESSAGE_MAP()
BOOL CMainDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置图标
SetIcon(theApp.LoadIcon(IDI_MAIN), FALSE);
// 创建状态栏,设置它的属性
m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0, 0), this, 101);
m_bar.SetBkColor(RGB(0xa6, 0xca, 0xf0)); // 背景色
int arWidth[] = { 200, -1 };
m_bar.SetParts(2, arWidth); // 分栏
m_bar.SetText( " ",1, 0); // 第一个栏的文本
m_bar.SetText(" 空闲", 0, 0); // 第二个栏的文本
// 初始化发送按钮和发送编辑框的状态
GetDlgItem(IDC_SEND)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO1)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO2)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO3)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO4)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO5)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_id)->EnableWindow(FALSE);
GetDlgItem(IDC_1)->EnableWindow(FALSE);
GetDlgItem(IDC_2)->EnableWindow(FALSE);
GetDlgItem(IDC_3)->EnableWindow(FALSE);
GetDlgItem(IDC_4)->EnableWindow(FALSE);
GetDlgItem(IDC_SENDFILE)->EnableWindow(FALSE);
GetDlgItem(IDC_RECVFILE)->EnableWindow(FALSE);
// 初始化连接套节字
m_socket = INVALID_SOCKET;
m_nClient = 0;
GetDlgItem(IDC_ADDR)->SetWindowText("202.117.67.234");
GetDlgItem(IDC_PORT)->SetWindowText("5000");
return TRUE;
}
void CMainDialog::OnCancel()
{
if(m_socket != INVALID_SOCKET)
::closesocket(m_socket);
CDialog::OnCancel();
}
void CMainDialog::OnButtonClear()
{
GetDlgItem(IDC_INFO)->SetWindowText("");
}
void CMainDialog::OnButtonConnect()
{
if(m_socket == INVALID_SOCKET) // 连接服务器
{
// 取得服务器地址
CString sAddr;
GetDlgItem(IDC_ADDR)->GetWindowText(sAddr);
if(sAddr.IsEmpty())
{
MessageBox("请输入服务器地址!");
return;
}
// 取得端口号
CString sPort;
GetDlgItem(IDC_PORT)->GetWindowText(sPort);
int nPort = atoi(sPort);
if(nPort < 1 || nPort > 65535)
{
MessageBox("端口号错误!");
return;
}
// 试图连接服务器
if(!Connect(sAddr, nPort))
{
MessageBox("连接服务器出错!");
return;
}
// 设置用户界面
GetDlgItem(IDC_CONNECT)->SetWindowText("取消");
m_bar.SetText(" 正在连接……", 0, 0);
}
else // 断开服务器
{
// 关闭套节字
::closesocket(m_socket);
m_socket = INVALID_SOCKET;
// 设置用户界面
GetDlgItem(IDC_CONNECT)->SetWindowText("连接服务器");
m_bar.SetText(" 空闲", 0, 0);
GetDlgItem(IDC_ADDR)->EnableWindow(TRUE);
GetDlgItem(IDC_PORT)->EnableWindow(TRUE);
GetDlgItem(IDC_TEXT)->EnableWindow(FALSE);
GetDlgItem(IDC_SEND)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO1)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO2)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO3)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO4)->EnableWindow(FALSE);
GetDlgItem(IDC_COMBO5)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_id)->EnableWindow(FALSE);
GetDlgItem(IDC_1)->EnableWindow(FALSE);
GetDlgItem(IDC_2)->EnableWindow(FALSE);
GetDlgItem(IDC_3)->EnableWindow(FALSE);
GetDlgItem(IDC_4)->EnableWindow(FALSE);
GetDlgItem(IDC_SENDFILE)->EnableWindow(FALSE);
GetDlgItem(IDC_RECVFILE)->EnableWindow(FALSE);
}
}
long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam)
{
// 取得有事件发生的套节字句柄
SOCKET s = wParam;
// 查看是否出错
if(WSAGETSELECTERROR(lParam))
{
if(m_socket != SOCKET_ERROR)
OnButtonConnect();
m_bar.SetText(" 连接出错!", 0, 0);
return 0;
}
// 处理发生的事件
switch(WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT: // 监听中的套接字检测到有连接进入
{
if(m_nClient < MAX_SOCKET)
{
// 接受连接请求,新的套节字client是新连接的套节字
SOCKET client = ::accept(s, NULL, NULL);
// 设置新的套节字为窗口通知消息类型
int i = ::WSAAsyncSelect(client,
m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);
AddClient(client);
}
else
{
MessageBox("连接客户太多!");
}
}
break;
case FD_CONNECT: // 套节字正确的连接到服务器
{
// 设置用户界面
GetDlgItem(IDC_CONNECT)->SetWindowText("断开连接");
GetDlgItem(IDC_ADDR)->EnableWindow(FALSE);
GetDlgItem(IDC_PORT)->EnableWindow(FALSE);
GetDlgItem(IDC_TEXT)->EnableWindow(TRUE);
GetDlgItem(IDC_SEND)->EnableWindow(TRUE);
GetDlgItem(IDC_COMBO1)->EnableWindow(TRUE);
GetDlgItem(IDC_COMBO2)->EnableWindow(TRUE);
GetDlgItem(IDC_COMBO3)->EnableWindow(TRUE);
GetDlgItem(IDC_COMBO4)->EnableWindow(TRUE);
GetDlgItem(IDC_COMBO5)->EnableWindow(TRUE);
GetDlgItem(IDC_EDIT_id)->EnableWindow(TRUE);
GetDlgItem(IDC_1)->EnableWindow(TRUE);
GetDlgItem(IDC_2)->EnableWindow(TRUE);
GetDlgItem(IDC_3)->EnableWindow(TRUE);
GetDlgItem(IDC_4)->EnableWindow(TRUE);
GetDlgItem(IDC_SENDFILE)->EnableWindow(TRUE);
GetDlgItem(IDC_RECVFILE)->EnableWindow(TRUE);
m_bar.SetText(" 已经连接到服务器", 0, 0);
}
break;
case FD_READ: // 套接字接受到对方发送过来的数据包
{
// 取得对方的IP地址和端口号(使用getpeername函数)
// Peer对方的地址信息
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
int nSockAddrLen = sizeof(sockAddr);
::getpeername(s, (SOCKADDR*)&sockAddr, &nSockAddrLen);
// 转化为主机字节顺序
int nPeerPort = ::ntohs(sockAddr.sin_port);
// 转化为字符串IP
CString sPeerIP = ::inet_ntoa(sockAddr.sin_addr);
// 取得对方的主机名称
// 取得网络字节顺序的IP值
DWORD dwIP = ::inet_addr(sPeerIP);
// 获取主机名称,注意其中第一个参数的转化
hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET);
char szHostName[256];
strncpy(szHostName, pHost->h_name, 256);
// 从服务器接受数据
char szText[1024] = { 0 };
::recv(s, szText, 1024, 0);
// 显示给用户
AddStringToList(CString(szText) + "\r\n"+"end");
//从服务器接收文件
/*CRect rect;
CWnd *pWnd=(CWnd *)->this->GetDlgItem(IDC_INFO);
pWnd->GetClientRect(rect);
CDC *pDC=pWnd->GetDC();*/
}
break;
case FD_CLOSE:
OnButtonConnect();
break;
}
return 0;
}
void CMainDialog::OnButtonSend()
{
if(m_socket == INVALID_SOCKET)
{
return;
}
// 取得要发送的字符串
CString sText;
GetDlgItem(IDC_TEXT)->GetWindowText(sText);
// 添加一个“回车换行”
// 注意,添加它并不是必须的,但是如果使用本软件作为客户端调试网络协议,
// 比如SMTP、FTP等,就要添加它了。因为这些协议都要求使用“回车换行”作为一个命令的结束标记
sText += "\r\n";
// 发送数据到服务器
int f,l;
if(f=::send(m_socket, sText, l=sText.GetLength(), 0) != -1)
{
AddStringToList(sText, FALSE);
GetDlgItem(IDC_TEXT)->SetWindowText("");
}
SetTimer(1,1000,NULL);
}
BOOL CMainDialog::Connect(LPCTSTR pszRemoteAddr, u_short nPort)
{
// 创建套节字
m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(m_socket == INVALID_SOCKET)
{
return FALSE;
}
// 设置socket为窗口通知消息类型
::WSAAsyncSelect(m_socket, m_hWnd,
WM_SOCKET, FD_CONNECT | FD_CLOSE | FD_WRITE | FD_READ);
// 假定szAddr是IP地址
ULONG uAddr = ::inet_addr(pszRemoteAddr);
if(uAddr == INADDR_NONE)
{
// 不是IP地址,就认为这是主机名称
// 从主机名取得IP地址
hostent* pHost = ::gethostbyname(pszRemoteAddr);
if(pHost == NULL)
{
::closesocket(m_socket);
m_socket = INVALID_SOCKET;
return FALSE;
}
// 得到以网络字节顺序排列的IP地址
uAddr = ((struct in_addr*)*(pHost->h_addr_list))->s_addr;
}
// 填写服务器地址信息
sockaddr_in remote;
remote.sin_addr.S_un.S_addr = uAddr;
remote.sin_family = AF_INET;
remote.sin_port = htons(nPort);
// 连接到远程机
::connect(m_socket, (sockaddr*)&remote, sizeof(sockaddr));
return TRUE;
}
void CMainDialog::AddStringToList(LPCTSTR pszText, BOOL bRecv)
{
CString strEdit;
GetDlgItem(IDC_INFO)->GetWindowText(strEdit);
if(bRecv)
{
strEdit += "【Recv】:";
strEdit += pszText;
//strEdit+="end";
}
else
{
strEdit += "【Send】:";
strEdit += pszText;
}
GetDlgItem(IDC_INFO)->SetWindowText(strEdit);
}
bool CMainDialog::AddClient(SOCKET s)
{
if(m_nClient < MAX_SOCKET)
{
// 添加新的成员
m_arClient[m_socket++] = s;
return TRUE;
}
return false;
}
void CMainDialog::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
CTime tNow;
tNow=CTime::GetCurrentTime();
CString sNow;
sNow+="D 1 ";
sNow+=m_ccb;
sNow+=tNow.Format(" 20%y%m%d %H%M%S ");
sNow+=m_ccb1;
sNow+=" ";
sNow+=m_ccb2;
sNow+=" ";
sNow+=m_ccbid;
sNow+="\r\n";
if(m_ccb.IsEmpty())
{
MessageBox("请输入相机ID","提示",MB_OK);
}
else if(m_ccb1.IsEmpty())
{
MessageBox("请输入测量周期","提示",MB_OK);
}
else if(m_ccb2.IsEmpty())
{
MessageBox("请输入测量类型ID","提示",MB_OK);
}
else if(m_ccbid.IsEmpty())
{
MessageBox("请输入测量类型总数","提示",MB_OK);
}
else
{
MessageBox(sNow,"测量消息");
sNow+="\r";
int f,l;
if(f=::send(m_socket, sNow, l=sNow.GetLength(), 0) != -1)
{
AddStringToList(sNow, FALSE);
GetDlgItem(IDC_TEXT)->SetWindowText("");}
}
UpdateData(FALSE);
}
void CMainDialog::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -