这是我遇到问题的聊天应用程序代码。
聊天系统通过拥有一个主服务器来工作,所有客户端都连接到该服务器。所以,这里是主服务器的代码。
#pragma comment(lib, "Ws2_32.lib")
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
using namespace std;
SOCKADDR_IN addr;
SOCKET sListen;
SOCKET sConnect;
SOCKET* Connections;
int addrlen = sizeof(addr);
int ConCounter = 0;
struct Buffer
{
int ID;
char Message[256];
};
int ServerThread(int ID)
{
Buffer sbuffer;
char* Recv = new char[256];
ZeroMemory(Recv, 256);
char* Send = new char[sizeof(Buffer)];
ZeroMemory(Send, sizeof(Buffer));
for(;; Sleep(10))
{
if(recv(Connections[ID], Recv, 256, NULL))
{
sbuffer.ID = ID;
memcpy(sbuffer.Message, Recv, 256);
memcpy(Send, &sbuffer, sizeof(Buffer));
for(int a = 0; a != ConCounter; a++)
{
if(Connections[a] == Connections[ID])
{
}
else
{
send(Connections[a], Send, sizeof(Buffer), NULL);
}
}
ZeroMemory(Recv, 256);
}
}
return 0;
}
int InitWinSock()
{
int RetVal = 0;
WSAData wsaData;
WORD DllVersion = MAKEWORD(2,1);
RetVal = WSAStartup(DllVersion, &wsaData);
return RetVal;
}
int main()
{
int RetVal = 0;
RetVal = InitWinSock();
if(RetVal != 0)
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
Connections = (SOCKET*)calloc(64, sizeof(SOCKET));
sListen = socket(AF_INET, SOCK_STREAM, NULL);
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(1234);
addr.sin_family = AF_INET;
bind(sListen, (SOCKADDR*)&addr, sizeof(addr));
listen(sListen, 64);
for(;; Sleep(50))
{
if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
{
Connections[ConCounter] = sConnect;
char* ID = new char[64];
ZeroMemory(ID, sizeof(ID));
itoa(ConCounter, ID, 10);
send(Connections[ConCounter], ID, sizeof(ID), NULL);
ConCounter = ConCounter + 1;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) ServerThread, (LPVOID)(ConCounter - 1), NULL, NULL);
}
}
return 0;
}
以下是客户端聊天的来源:
#pragma comment(lib, "Ws2_32.lib")
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
using namespace std;
SOCKADDR_IN addr;
SOCKET sConnect;
// For this we need to send two information at one time:
// 1. The main message
// 2. The ID
// To send more than one information I will use a struct
struct Buffer
{
int ID;
char Message[256];
};
int ClientThread()
{
Buffer sbuffer;
char buffer[sizeof(sbuffer)] = {0};
for(;; Sleep(10))
{
// The server will send a struct to the client
// containing message and ID
// But send only accepts a char as buffer parameter
// so here we need to recv a char buffer and then
// we copy the content of this buffer to our struct
if(recv(sConnect, buffer, sizeof(sbuffer), NULL))
{
memcpy(&sbuffer, buffer, sizeof(sbuffer));
cout << "<Client " << sbuffer.ID << ":> " << sbuffer.Message <<endl;
}
}
return 0;
}
int main()
{
system("cls");
int RetVal = 0;
WSAData wsaData;
WORD DllVersion = MAKEWORD(2,1);
RetVal = WSAStartup(DllVersion, &wsaData);
if(RetVal != 0)
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(1234);
addr.sin_family = AF_INET;
cout << "Connect to Masterserver? [ENTER]" <<endl;
getchar();
RetVal = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
if(RetVal != 0)
{
MessageBoxA(NULL, "Could not connect to server", "Error", MB_OK | MB_ICONERROR);
main();
}
else
{
int ID;
char* cID = new char[64];
ZeroMemory(cID, 64);
recv(sConnect, cID, 64, NULL);
ID = atoi(cID);
cout << "Connected" <<endl;
cout << "You are Client No: " << ID <<endl;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) ClientThread, NULL, NULL, NULL);
for(;; Sleep(10))
{
char* buffer = new char[256];
ZeroMemory(buffer, 256);
cin >> buffer;
getchar();
send(sConnect, buffer, 256, NULL);
}
}
return 0;
}
现在,一切正常,除非您连接两个客户端(运行应用程序两次)并关闭其中一个客户端,关闭应用程序的客户端向聊天中发送无限的消息,这些消息永远不会停止!有什么帮助解决这个问题吗?
如果可能的话,我想请人帮我评论源代码!
更新代码:
#pragma comment(lib, "Ws2_32.lib")
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;
SOCKADDR_IN addr;
SOCKET sConnect;
struct Buffer
{
int ID;
char Message[256];
};
int ClientThread()
{
Buffer sbuffer;
string buffer;
//char buffer[sizeof(sbuffer)] = {0};
for(;; Sleep(10))
{
if(recv(sConnect, buffer.c_str(), sizeof(sbuffer), NULL)!=SOCKET_ERROR)
{
strncpy(sbuffer.Message, buffer.c_str(), sizeof(sbuffer.Message));
cout << "<Client " << sbuffer.ID << ":> " << sbuffer.Message <<endl;
}
}
return 0;
}
int main()
{
system("cls");
int RetVal = 0;
WSAData wsaData;
WORD DllVersion = MAKEWORD(2,1);
RetVal = WSAStartup(DllVersion, &wsaData);
if(RetVal != 0)
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(1234);
addr.sin_family = AF_INET;
cout << "Connect to Masterserver? [ENTER]" <<endl;
getchar();
RetVal = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
if(RetVal != 0)
{
MessageBoxA(NULL, "Could not connect to server", "Error", MB_OK | MB_ICONERROR);
main();
}
else
{
int ID;
char* cID = new char[64];
ZeroMemory(cID, 64);
recv(sConnect, cID, 64, NULL);
ID = atoi(cID);
cout << "Connected" <<endl;
cout << "You are Client No: " << ID <<endl;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) ClientThread, NULL, NULL, NULL);
for(;; Sleep(10))
{
char* buffer = new char[256];
ZeroMemory(buffer, 256);
getline(cin,buffer);
//cin >> buffer;
getchar();
send(sConnect, buffer, 256, NULL);
}
}
return 0;
}