Windows下实现 C/C++下TCP, 服务器/客户端 "多人聊天室",客户端用户需要先注册再登陆,用户的注册信息保存在txt文件中,由服务器读取txt文件并接受用户客户端的连接,不能使用unistd.h库中的内容
时间: 2023-06-18 22:06:02 浏览: 100
实现一个 TCP 多人聊天室需要以下几个步骤:
1. 创建服务器端和客户端的套接字
2. 将服务器端套接字绑定到一个 IP 地址和端口号上,并监听客户端的连接请求
3. 当有客户端连接时,服务器端接受连接请求,创建一个新的线程处理客户端的请求
4. 在客户端连接成功后,客户端先进行注册,将注册信息发送给服务器端进行验证,如果验证通过,则允许客户端登录聊天室
5. 客户端登录成功后,可以向服务器端发送消息,服务器端将消息转发给所有在线的客户端
6. 客户端可以随时退出聊天室,服务器端也会将其从在线列表中删除
以下是一个示例代码,其中用户的注册信息保存在 "user.txt" 文件中,每行包含用户名和密码,使用空格分隔。
服务器端代码:
```c++
#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <vector>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define MAX_BUFFER_SIZE 1024
#define MAX_CLIENTS 10
struct User {
std::string name;
std::string password;
};
std::vector<User> users;
std::vector<SOCKET> clients;
void load_users() {
std::ifstream file("user.txt");
if (!file.is_open()) {
std::cerr << "Error: cannot open file 'user.txt'" << std::endl;
exit(1);
}
std::string line;
while (std::getline(file, line)) {
std::istringstream iss(line);
std::string name, password;
iss >> name >> password;
users.push_back({name, password});
}
}
bool authenticate(const std::string& name, const std::string& password) {
for (const auto& user : users) {
if (user.name == name && user.password == password) {
return true;
}
}
return false;
}
void handle_client(SOCKET client_socket) {
char buffer[MAX_BUFFER_SIZE];
std::string name;
bool authenticated = false;
while (true) {
int bytes_received = recv(client_socket, buffer, MAX_BUFFER_SIZE, 0);
if (bytes_received == SOCKET_ERROR) {
std::cerr << "Error: failed to receive data from client" << std::endl;
break;
}
if (bytes_received == 0) {
std::cout << "Client disconnected" << std::endl;
break;
}
std::string message(buffer, bytes_received);
if (!authenticated) {
std::istringstream iss(message);
std::string command, username, password;
iss >> command >> username >> password;
if (command == "REGISTER") {
bool found = false;
for (const auto& user : users) {
if (user.name == username) {
found = true;
break;
}
}
if (found) {
std::string response = "ERROR User already exists\n";
send(client_socket, response.c_str(), response.size(), 0);
} else {
users.push_back({username, password});
std::string response = "OK Registered successfully\n";
send(client_socket, response.c_str(), response.size(), 0);
}
} else if (command == "LOGIN") {
if (authenticate(username, password)) {
name = username;
authenticated = true;
clients.push_back(client_socket);
std::string response = "OK Logged in successfully\n";
send(client_socket, response.c_str(), response.size(), 0);
std::cout << "Client " << name << " connected" << std::endl;
} else {
std::string response = "ERROR Invalid username or password\n";
send(client_socket, response.c_str(), response.size(), 0);
}
} else {
std::string response = "ERROR Invalid command\n";
send(client_socket, response.c_str(), response.size(), 0);
}
} else {
std::string message_with_name = name + ": " + message;
for (const auto& client : clients) {
if (client != client_socket) {
send(client, message_with_name.c_str(), message_with_name.size(), 0);
}
}
}
}
closesocket(client_socket);
clients.erase(std::remove(clients.begin(), clients.end(), client_socket), clients.end());
}
int main() {
WSADATA wsa_data;
int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (result != 0) {
std::cerr << "Error: failed to initialize Winsock" << std::endl;
return 1;
}
load_users();
SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
std::cerr << "Error: failed to create server socket" << std::endl;
WSACleanup();
return 1;
}
sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(1234);
result = bind(server_socket, (sockaddr*)&server_address, sizeof(server_address));
if (result == SOCKET_ERROR) {
std::cerr << "Error: failed to bind server socket" << std::endl;
closesocket(server_socket);
WSACleanup();
return 1;
}
result = listen(server_socket, MAX_CLIENTS);
if (result == SOCKET_ERROR) {
std::cerr << "Error: failed to listen on server socket" << std::endl;
closesocket(server_socket);
WSACleanup();
return 1;
}
std::cout << "Server started" << std::endl;
while (true) {
sockaddr_in client_address;
int client_address_size = sizeof(client_address);
SOCKET client_socket = accept(server_socket, (sockaddr*)&client_address, &client_address_size);
if (client_socket == INVALID_SOCKET) {
std::cerr << "Error: failed to accept client connection" << std::endl;
break;
}
std::thread t(handle_client, client_socket);
t.detach();
}
closesocket(server_socket);
WSACleanup();
return 0;
}
```
客户端代码:
```c++
#include <iostream>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define MAX_BUFFER_SIZE 1024
int main() {
WSADATA wsa_data;
int result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (result != 0) {
std::cerr << "Error: failed to initialize Winsock" << std::endl;
return 1;
}
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket == INVALID_SOCKET) {
std::cerr << "Error: failed to create client socket" << std::endl;
WSACleanup();
return 1;
}
sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = htons(1234);
result = connect(client_socket, (sockaddr*)&server_address, sizeof(server_address));
if (result == SOCKET_ERROR) {
std::cerr << "Error: failed to connect to server" << std::endl;
closesocket(client_socket);
WSACleanup();
return 1;
}
std::cout << "Connected to server" << std::endl;
std::string name, password;
std::cout << "Enter your name: ";
std::cin >> name;
std::cout << "Enter your password: ";
std::cin >> password;
std::string request = "LOGIN " + name + " " + password + "\n";
send(client_socket, request.c_str(), request.size(), 0);
char buffer[MAX_BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, MAX_BUFFER_SIZE, 0);
if (bytes_received == SOCKET_ERROR) {
std::cerr << "Error: failed to receive data from server" << std::endl;
closesocket(client_socket);
WSACleanup();
return 1;
}
std::string response(buffer, bytes_received);
if (response == "OK Logged in successfully\n") {
std::cout << "Logged in successfully" << std::endl;
std::thread t([&client_socket]() {
while (true) {
char buffer[MAX_BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, MAX_BUFFER_SIZE, 0);
if (bytes_received == SOCKET_ERROR) {
std::cerr << "Error: failed to receive data from server" << std::endl;
break;
}
if (bytes_received == 0) {
std::cout << "Server disconnected" << std::endl;
break;
}
std::string message(buffer, bytes_received);
std::cout << message;
}
closesocket(client_socket);
exit(0);
});
t.detach();
while (true) {
std::string message;
std::getline(std::cin, message);
if (message == "QUIT") {
break;
}
send(client_socket, message.c_str(), message.size(), 0);
}
} else {
std::cerr << "Error: " << response;
}
closesocket(client_socket);
WSACleanup();
return 0;
}
```
阅读全文