- gf25152 的博客
茶水间
- @ 2026-5-6 16:46:58
加-lws2_32
#include <iostream>
#include <string>
#include <cstring>
#include <winsock2.h>
#include <windows.h>
#include <process.h>
#ifdef __GNUC__
#pragma comment(lib, "ws2_32")
#endif
using namespace std;
// 全局变量
bool g_running = true;
SOCKET g_sock = INVALID_SOCKET;
sockaddr_in g_remote_addr;
// 接收线程函数
unsigned int __stdcall ReceiveThreadFunc(void* pArg) {
char buffer[1024];
sockaddr_in senderAddr;
int senderAddrLen = sizeof(senderAddr);
while (g_running) {
memset(buffer, 0, sizeof(buffer));
// 接收数据
int result = recvfrom(g_sock, buffer, sizeof(buffer) - 1, 0,
(sockaddr*)&senderAddr, &senderAddrLen);
if (result > 0) {
// 成功收到消息
cout << "\r[收到] " << buffer << " \r";
cout << "[发送] ";
fflush(stdout);
}
else if (result == SOCKET_ERROR) {
int errCode = WSAGetLastError();
// 【关键修改】如果是 10054 (连接重置),通常是因为之前发送的数据对方没收
// 我们不应该退出,而是应该忽略这次错误,继续循环等待
if (errCode == WSAECONNRESET) {
// 可以选择打印一个看不见的字符刷新界面,或者什么都不做
// cerr << "\r[系统] 远程主机重置连接(10054),请检查对方是否在线..." << endl;
continue;
}
// 如果是 Socket 被关闭导致的错误,则退出线程
else if (errCode == WSAENOTSOCK) {
break;
}
// 其他错误
else {
cerr << "\r[系统] 接收错误: " << errCode << " \r";
cerr << "[发送] ";
fflush(stdout);
}
}
Sleep(100);
}
return 0;
}
int main() {
cout << "=== 局域网UDP聊天室 (C++98版) ===" << endl;
// 1. 初始化 Winsock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSA初始化失败!" << endl;
return -1;
}
// 2. 创建 Socket
g_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (g_sock == INVALID_SOCKET) {
cout << "Socket创建失败!" << endl;
WSACleanup();
return -1;
}
// 3. 绑定本地端口
sockaddr_in localAddr;
memset(&localAddr, 0, sizeof(localAddr));
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(60001);
localAddr.sin_addr.s_addr = INADDR_ANY;
if (bind(g_sock, (sockaddr*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) {
cout << "绑定端口失败! 可能是端口被占用。" << endl;
closesocket(g_sock);
WSACleanup();
return -1;
}
// 4. 设置目标IP
string targetIP;
int targetPort = 60001;
cout << "请输入对方IP地址: ";
cin >> targetIP;
cin.ignore();
memset(&g_remote_addr, 0, sizeof(g_remote_addr));
g_remote_addr.sin_family = AF_INET;
g_remote_addr.sin_port = htons(targetPort);
g_remote_addr.sin_addr.s_addr = inet_addr(targetIP.c_str());
if (g_remote_addr.sin_addr.s_addr == INADDR_NONE) {
cout << "无效的IP地址!" << endl;
closesocket(g_sock);
WSACleanup();
return -1;
}
cout << "已连接到 " << targetIP << ":" << targetPort << endl;
cout << "开始聊天 (输入 'exit' 退出):" << endl;
// 5. 启动线程
unsigned int threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ReceiveThreadFunc, NULL, 0, &threadID);
// 6. 主循环
string msg;
while (g_running) {
cout << "[发送] ";
getline(cin, msg);
if (msg == "exit") {
g_running = false;
break;
}
if (!msg.empty()) {
int sendResult = sendto(g_sock, msg.c_str(), msg.length(), 0,
(sockaddr*)&g_remote_addr, sizeof(g_remote_addr));
if (sendResult == SOCKET_ERROR) {
// 发送也可能报 10054,如果此时网络不通
int err = WSAGetLastError();
if(err == WSAECONNRESET) {
cout << "[系统] 警告:发送失败,对方可能未开启或未响应(10054)" << endl;
}
}
}
}
// 7. 清理
closesocket(g_sock);
if (hThread) {
WaitForSingleObject(hThread, 2000);
CloseHandle(hThread);
}
WSACleanup();
return 0;
}