由于使用WIN,直接使用CreateThread方式。线程的释放,自行处理。(虽然代码中止会return 0)
客户端代码:
#include <winsock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <random>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
//获取随机长度的字符串
string GetLengStr(int length) {
string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
std::string result;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, charset.size() - 1);
for (int i = 0; i < length; ++i) {
result += charset[dis(gen)];
}
return result;
}
int main()
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
cout << "加载winsock.dll失败!" << endl;
return 0;
}
//创建套接字
SOCKET sock_client;
if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;
WSACleanup();
return 0;
}
//连接服务器
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9999); //端口
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//绑定本机的环回地址
int len = sizeof(sockaddr_in);
if (connect(sock_client, (SOCKADDR*)&addr, len) == SOCKET_ERROR) {
cout << "连接失败!错误代码:" << WSAGetLastError() << endl;
return 0;
}
cout << "开始和服务器通讯" << endl;
int leng = 10;
string str;
while (1)
{
if (leng >= 32) { //别一直循环
break;//跳出,可以自己做重连动作
}
leng++;
str = GetLengStr(leng); //获取随机长度的字符串
char setData[1024]; //定义一个最大1024的变量
int len = str.copy(setData, 1024); //获取实际的有效长度
int ret = send(sock_client, setData, len, 0);
if (ret == SOCKET_ERROR || ret == 0)
{
cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl;
break;
}
else {
cout << "信息发送成功!发送的内容:" << setData << "长度"<< sizeof(len)<<endl;
Sleep(2000);
}
char getData[1024];
int ret1 = recv(sock_client, getData, sizeof(getData), 0);
if (ret1 == SOCKET_ERROR || ret1 == 0)
{
break; //跳出,可以自己做重连动作
}
else {
cout << "获取内容:" << getData << endl;
}
}
closesocket(sock_client);
WSACleanup();
return 0;
}
MFC版:
#include <winsock2.h>
#include <WS2tcpip.h>
//MFC里只需要包含以上2文件即可
DWORD WINAPI TcpServerRun(LPVOID lpParameter) {
SOCKET sock = (SOCKET)lpParameter;
//先设置一个接收报文的长度
string str;
CString cstr;
CString length;
while (true) {
//4个字节的,用来统计获取的包数量,然后第二次才是执行内容获取
char bufferdata[1024];
int ret = recv(sock, bufferdata, sizeof(bufferdata), 0);
if (ret == SOCKET_ERROR || ret == 0)
{
closesocket(sock); return 0;
char bufferdata[1024];
int ret = recv(sock, bufferdata, sizeof(bufferdata), 0);
if (ret == SOCKET_ERROR || ret == 0)
{
closesocket(sock); return 0;
}
str = bufferdata; //先把获取的给string
cstr = L"收到内容:";
cstr += str.c_str();
cstr += "长度:";
length.Format(TEXT("%d"), str.size());
cstr += length;
char setData[32] = "发回给客户端的动作";
int ret1 = send(sock, setData, sizeof(setData), 0);
if (ret1 == SOCKET_ERROR || ret1 == 0) {
closesocket(sock); return 0;
}
}
return 0;
}
//创建一个TCP服务端
DWORD WINAPI TcpServer(LPVOID lpParameter) {
C控制程序Dlg* pThis = (C控制程序Dlg*)lpParameter;
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
pThis->MessageBox(L"加载winsock.dll失败!");
return 0;
}
//创建套接字
SOCKET sock_server;
if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
pThis->MessageBox(L"创建套接字失败!!");
WSACleanup();
return 0;
}
//绑定端口和Ip
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//绑定本机的环回地址
if (SOCKET_ERROR == bind(sock_server, (SOCKADDR*)&addr, sizeof(sockaddr_in)))
{
pThis->MessageBox(L"地址绑定失败!");
closesocket(sock_server);
WSACleanup();
return 0;
}
//将套接字设为监听状态
listen(sock_server, 0);
//主线程循环接收客户端的连接
while (1)
{
sockaddr_in addrClient;
int len = sizeof(sockaddr_in);
SOCKET sock = accept(sock_server, (SOCKADDR*)&addrClient, &len);
if (sock != INVALID_SOCKET)
{
//pThis->MessageBox(L"检测到TCP客户端连接");
CreateThread(0, 0, TcpServerRun,(LPVOID)sock, 0, 0); //创建一个线程,传入(LPVOID)sock资源
}
}
return 0;
}
这里自己用一个button事件来触发调用,这里是线程里创建线程。否则主进程会卡住挂起。
void C我的TCP服务端Dlg::OnBnClickedButton1(){
CreateThread(0, 0, TcpServer, (LPVOID)this, 0, 0); //创建TCP服务端线程。
}
再来一个cmd版本的,注意,MFC框架里,内容的长度无需特别操作。注意,编码等问题,包括获取的,自行处理了。
#include <winsock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <random>
#include <string>
#include <Windows.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
DWORD WINAPI TcpServerRun(LPVOID lpParameter) {
SOCKET sock = (SOCKET)lpParameter;
//先设置一个接收报文的长度
string str;
while (true) {
//4个字节的,用来统计获取的包数量,然后第二次才是执行内容获取
char msgbuffe[1024];
int ret = recv(sock, msgbuffe, sizeof(msgbuffe), 0);
if (ret == SOCKET_ERROR || ret == 0)
{
break; //跳出并且关闭
}
str = msgbuffe;
str.copy(msgbuffe, 1024); //获取实际的有效长度
cout << msgbuffe << endl;
char setData[32] = "发回给客户端的动作";
int ret1 = send(sock, setData, sizeof(setData), 0);
if (ret1 == SOCKET_ERROR || ret1 == 0) {
break; //跳出并且关闭
}
}
closesocket(sock); //记得释放socket
WSACleanup();
return 0;
}
//创建一个TCP服务端
int main() {
system("chcp 65001");
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
cout << "加载winsock.dll失败!" << endl;
return 0;
}
//创建套接字
SOCKET sock_server;
if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
cout << "创建套接字失败!!" << endl;
WSACleanup();
return 0;
}
//绑定端口和Ip
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//绑定本机的环回地址
if (SOCKET_ERROR == bind(sock_server, (SOCKADDR*)&addr, sizeof(sockaddr_in)))
{
cout << "地址绑定失败!" << endl;
closesocket(sock_server);
WSACleanup();
return 0;
}
//将套接字设为监听状态
listen(sock_server, 0);
while (1)
{
sockaddr_in addrClient;
int len = sizeof(sockaddr_in);
SOCKET sock = accept(sock_server, (SOCKADDR*)&addrClient, &len);
if (sock != INVALID_SOCKET)
{
CreateThread(0, 0, TcpServerRun, (LPVOID)sock, 0, 0); //创建一个线程,传入(LPVOID)sock资源
}
}
return 0;
}
关于作者