实现 C/C++下TCP, 服务器/客户端 "多人聊天室",客户端用户需要登陆,用户账号密码用txt保存并读取,要求在windows下运行
时间: 2023-06-19 21:04:48 浏览: 141
实现一个基于 TCP 的多人聊天室,需要分为服务器端和客户端两个部分。
服务器端:
服务器端需要监听指定端口,等待客户端连接。当有新的客户端连接时,服务器需要为其分配一个唯一的 ID,并且将其添加到客户端列表中。
服务器需要维护一个聊天室的状态,比如在线用户列表和聊天记录等。当有用户发送消息时,服务器需要将消息广播给所有在线用户。
客户端:
客户端需要先进行登录验证,可以通过读取本地存储的账号密码文本文件进行验证。如果验证通过,客户端可以连接到服务器,并加入聊天室。
客户端可以发送消息给服务器,服务器会将其广播给所有在线用户。客户端也需要接收其他用户发送的消息,并将其显示在界面上。
下面是一个 C++ 实现的简单示例代码,仅供参考:
服务器端代码:
```cpp
#include <iostream>
#include <vector>
#include <string>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
const int BUF_SIZE = 1024;
const int MAX_CLIENTS = 10;
struct Client {
int id;
SOCKET socket;
sockaddr_in addr;
};
vector<Client> clients;
int nextId = 1;
void broadcastMessage(const string& message, int senderId) {
cout << "Broadcasting message: " << message << endl;
for (auto& client : clients) {
if (client.id != senderId) {
send(client.socket, message.c_str(), message.length(), 0);
}
}
}
void handleClient(Client& client) {
char buf[BUF_SIZE];
while (true) {
int len = recv(client.socket, buf, BUF_SIZE, 0);
if (len <= 0) {
// client disconnected
cout << "Client " << client.id << " disconnected." << endl;
closesocket(client.socket);
clients.erase(remove(clients.begin(), clients.end(), client), clients.end());
break;
}
buf[len] = '\0';
string message(buf);
cout << "Received message from client " << client.id << ": " << message << endl;
broadcastMessage(message, client.id);
}
}
int main() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(12345);
bind(listener, (sockaddr*)&addr, sizeof(addr));
listen(listener, MAX_CLIENTS);
cout << "Server started. Listening on port 12345..." << endl;
while (true) {
SOCKET clientSocket = accept(listener, NULL, NULL);
Client client{ nextId++, clientSocket };
getpeername(clientSocket, (sockaddr*)&client.addr, (int*)sizeof(client.addr));
clients.push_back(client);
cout << "Client " << client.id << " connected from " << inet_ntoa(client.addr.sin_addr) << endl;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)handleClient, (LPVOID)&client, 0, NULL);
}
WSACleanup();
return 0;
}
```
客户端代码:
```cpp
#include <iostream>
#include <string>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
const int BUF_SIZE = 1024;
bool login(SOCKET socket) {
string username, password;
cout << "Please enter your username: ";
cin >> username;
cout << "Please enter your password: ";
cin >> password;
// TODO: read username and password from file and compare with input
string message = "LOGIN " + username + " " + password;
send(socket, message.c_str(), message.length(), 0);
char buf[BUF_SIZE];
int len = recv(socket, buf, BUF_SIZE, 0);
if (len <= 0) {
cout << "Server disconnected." << endl;
return false;
}
buf[len] = '\0';
string response(buf);
if (response == "OK") {
cout << "Login succeeded." << endl;
return true;
} else {
cout << "Login failed: " << response << endl;
return false;
}
}
void receiveMessages(SOCKET socket) {
char buf[BUF_SIZE];
while (true) {
int len = recv(socket, buf, BUF_SIZE, 0);
if (len <= 0) {
cout << "Server disconnected." << endl;
break;
}
buf[len] = '\0';
string message(buf);
cout << "Received message: " << message << endl;
}
}
int main() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(socketClient, (sockaddr*)&serverAddr, sizeof(serverAddr));
if (!login(socketClient)) {
return 0;
}
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)receiveMessages, (LPVOID)&socketClient, 0, NULL);
string message;
while (true) {
cout << "> ";
getline(cin, message);
send(socketClient, message.c_str(), message.length(), 0);
}
WSACleanup();
return 0;
}
```
阅读全文