实现 C/C++下TCP, 服务器/客户端 "多人聊天室",客户端用户需要登陆,用户账号密码用txt保存并读取
时间: 2023-06-19 07:04:43 浏览: 146
C++实现多人聊天室,C/S模式
实现C/C++下TCP服务器/客户端多人聊天室,需要以下步骤:
1. 确定通信协议
在TCP/IP协议中,服务器和客户端之间的通信使用套接字(Socket)实现。服务器和客户端之间的通信协议需要在客户端和服务器之间进行协商,确定信息的格式和传输方式。
2. 设计服务器程序
服务器需要具有以下功能:
- 监听客户端的连接请求。
- 接收客户端发送的信息,并将信息转发给其他客户端。
- 维护客户端连接状态,包括处理连接请求、处理断开连接请求等。
3. 设计客户端程序
客户端需要具有以下功能:
- 连接服务器。
- 发送消息给服务器。
- 接收服务器转发的其他客户端发送的消息。
- 登录验证。
4. 实现用户账号密码用txt保存并读取
可以使用文件读写API实现用户账号密码用txt保存并读取。具体实现可以在服务器端或客户端实现。
下面是一个简单的C++代码实现多人聊天室的服务器和客户端:
服务器端代码:
```c++
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <map>
#define MAX_CLIENT_NUM 100
#define BUFF_SIZE 1024
using namespace std;
struct ClientInfo
{
int sock_fd;
string username;
};
map<int, ClientInfo> client_list; // 客户端列表
pthread_mutex_t mutex_client_list; // 客户端列表的锁
void send_message(const char* message, int sender_sock_fd)
{
pthread_mutex_lock(&mutex_client_list);
for (auto& client : client_list)
{
if (client.second.sock_fd != sender_sock_fd)
{
write(client.second.sock_fd, message, strlen(message));
}
}
pthread_mutex_unlock(&mutex_client_list);
}
void* handle_client(void* arg)
{
int sock_fd = *(int*)arg;
char buff[BUFF_SIZE] = {0};
string username;
// 接收客户端的用户名
read(sock_fd, buff, BUFF_SIZE);
username = buff;
pthread_mutex_lock(&mutex_client_list);
ClientInfo client_info;
client_info.sock_fd = sock_fd;
client_info.username = username;
client_list.insert(make_pair(sock_fd, client_info));
pthread_mutex_unlock(&mutex_client_list);
printf("User %s connected.\n", username.c_str());
// 广播有新用户连接
string message = username + " joined the room.\n";
send_message(message.c_str(), sock_fd);
// 循环处理客户端消息
while (true)
{
memset(buff, 0, sizeof(buff));
int recv_len = read(sock_fd, buff, BUFF_SIZE);
if (recv_len <= 0)
{
// 客户端断开连接
pthread_mutex_lock(&mutex_client_list);
client_list.erase(sock_fd);
pthread_mutex_unlock(&mutex_client_list);
printf("User %s disconnected.\n", username.c_str());
// 广播有用户断开连接
string message = username + " left the room.\n";
send_message(message.c_str(), sock_fd);
close(sock_fd);
break;
}
// 广播客户端发送的消息
message = username + ": " + buff;
send_message(message.c_str(), sock_fd);
}
return NULL;
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Usage: %s <port>\n", argv[0]);
exit(-1);
}
int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock_fd < 0)
{
perror("socket");
exit(-1);
}
int port = atoi(argv[1]);
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(server_sock_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
perror("bind");
exit(-1);
}
if (listen(server_sock_fd, MAX_CLIENT_NUM) < 0)
{
perror("listen");
exit(-1);
}
pthread_mutex_init(&mutex_client_list, NULL);
while (true)
{
sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_sock_fd = accept(server_sock_fd, (sockaddr*)&client_addr, &client_addr_len);
if (client_sock_fd < 0)
{
perror("accept");
continue;
}
pthread_t thread_id;
pthread_create(&thread_id, NULL, handle_client, &client_sock_fd);
pthread_detach(thread_id);
}
return 0;
}
```
客户端代码:
```c++
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFF_SIZE 1024
using namespace std;
int main(int argc, char* argv[])
{
if (argc != 3)
{
printf("Usage: %s <ip> <port>\n", argv[0]);
exit(-1);
}
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
{
perror("socket");
exit(-1);
}
int port = atoi(argv[2]);
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr) < 0)
{
perror("inet_pton");
exit(-1);
}
if (connect(sock_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
perror("connect");
exit(-1);
}
char buff[BUFF_SIZE] = {0};
string username, password;
// 登录验证
printf("Please enter your username: ");
cin >> username;
printf("Please enter your password: ");
cin >> password;
sprintf(buff, "%s:%s", username.c_str(), password.c_str());
write(sock_fd, buff, strlen(buff));
// 循环处理用户输入和服务器消息
while (true)
{
fd_set read_set;
FD_ZERO(&read_set);
FD_SET(STDIN_FILENO, &read_set);
FD_SET(sock_fd, &read_set);
select(sock_fd + 1, &read_set, NULL, NULL, NULL);
if (FD_ISSET(STDIN_FILENO, &read_set))
{
// 从标准输入读取用户输入,发送给服务器
string message;
getline(cin, message);
sprintf(buff, "%s", message.c_str());
write(sock_fd, buff, strlen(buff));
}
if (FD_ISSET(sock_fd, &read_set))
{
// 从服务器读取消息,输出到标准输出
memset(buff, 0, sizeof(buff));
int recv_len = read(sock_fd, buff, BUFF_SIZE);
if (recv_len <= 0)
{
printf("Disconnected from server.\n");
break;
}
printf("%s", buff);
}
}
close(sock_fd);
return 0;
}
```
阅读全文