最终界面如图所示:
不管客户端还是服务器,头文件添加爱
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#include <string>
#include <iostream>
#include <thread>
//using namespace std;
#pragma comment(lib, "ws2_32.lib")
用到 C++ 11 的 THREAD,VS2013 以上版本,本例用 VS2017 编译。
客户端:.H 文件
public:
bool bRunning;
std::thread threadid;
void GetDataThread();
void PrintToList(CString info, bool bclient = false);
SOCKET mSocketClient; //客户端套接字
SOCKADDR_IN mSocketAddress; //服务器地址
char mReadBuf[BUF_SIZE]; //接收数据缓冲区
char mSendBuf[BUF_SIZE]; //返回给客户端得数据
public:
afx_msg void OnBnClickedBtstart();
afx_msg void OnBnClickedBtstop();
afx_msg void OnBnClickedBtsend();
客户端:CPP 文件
void CTCPCLIENTDlg::GetDataThread() //获取消息线程
{
while (bRunning == true)
{
//接收客户端数据
ZeroMemory(mReadBuf, BUF_SIZE);
//第一个参数:指向一块准备用0来填充的内存区域的开始地址。
//第二个参数:准备用0来填充的内存区域的大小,按字节来计算。
int retVal = recv(mSocketClient, mReadBuf, BUF_SIZE, 0); //从一个套接口接收数据
//第一个参数:一个标识已连接套接口的描述字
//第二个参数:用于接收数据的缓冲区。
//第三个参数:缓冲区长度
//第四个参数:指定调用方式
if (SOCKET_ERROR == retVal)
{
PrintToList(CString("RECV FAILED"), true);
closesocket(mSocketClient); //关闭套接字
WSACleanup(); //释放套接字资源;
AfxMessageBox(L"RECV FAILED");
break;
}
if (retVal > 0)
{
PrintToList(CString(mReadBuf), false);
}
}
}
void CTCPCLIENTDlg::PrintToList(CString info, bool bclient)
{
SYSTEMTIME stime;
CString strtime;
GetLocalTime(&stime);
strtime.Format(_T("%02d:%02d:%02d"), stime.wHour, stime.wMinute, stime.wSecond);
//获取当前记录条数
CListCtrl * list = (CListCtrl*)GetDlgItem(IDC_LTGET);
CString role = bclient ? _T("客户端说") : _T("服务器说");
int nIndex = list->GetItemCount();
list->InsertItem(nIndex, strtime);
list->SetItemText(nIndex, 1, role);
list->SetItemText(nIndex, 2, info);
list->SendMessage(WM_VSCROLL, SB_BOTTOM, NULL);
}
void CTCPCLI