编写一个基于windows socket的c语言程序。该程序允许多个用户同时在互联网上进行沟通。该程序应该包括以下模块:1.数据库:用于存储和组织用户信息,群组类别和聊天历史。2.用户管理:允许管理员/用户添加、更新或删除账户。3.连接:支持至少三个并发连接。4.聊天历史记录:记录每个会话的IP地址和连接时间。
时间: 2023-06-18 20:06:50 浏览: 164
以下是一个基于Windows socket的C语言程序,实现了多个用户在互联网上进行沟通,包括数据库模块、用户管理模块、连接模块和聊天历史记录模块。
注意:这只是一个基本框架,需要根据实际需求进行修改和完善。
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <mysql.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "libmysql.lib")
#define MAX_CLIENTS 3
#define BUFFER_SIZE 1024
#define SERVER_PORT 8888
// 数据库连接信息
#define DB_HOST "localhost"
#define DB_USER "root"
#define DB_PASSWORD "123456"
#define DB_NAME "chatroom"
// 客户端信息结构
typedef struct {
char username[32];
char password[32];
char ip[16];
int port;
} client_info;
// TCP连接信息结构
typedef struct {
SOCKET socket;
char ip[16];
int port;
} tcp_info;
// 聊天记录结构
typedef struct {
int id;
char sender[32];
char receiver[32];
char content[256];
char datetime[32];
} chat_record;
// 数据库连接
MYSQL* connect_db() {
MYSQL* conn = mysql_init(NULL);
if (conn == NULL) {
printf("Failed to init MySQL.\n");
return NULL;
}
if (mysql_real_connect(conn, DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, 0, NULL, 0) == NULL) {
printf("Failed to connect to MySQL: %s\n", mysql_error(conn));
mysql_close(conn);
return NULL;
}
return conn;
}
// 关闭数据库连接
void close_db(MYSQL* conn) {
mysql_close(conn);
}
// 用户登录
int login(MYSQL* conn, client_info* client) {
char sql[BUFFER_SIZE];
sprintf(sql, "SELECT * FROM users WHERE username='%s' AND password='%s'", client->username, client->password);
if (mysql_query(conn, sql) != 0) {
printf("Failed to query from MySQL: %s\n", mysql_error(conn));
return 0;
}
MYSQL_RES* res = mysql_store_result(conn);
if (mysql_num_rows(res) == 0) {
printf("Invalid username or password.\n");
mysql_free_result(res);
return 0;
}
mysql_free_result(res);
return 1;
}
// 用户注册
int register_user(MYSQL* conn, client_info* client) {
char sql[BUFFER_SIZE];
sprintf(sql, "INSERT INTO users(username,password,ip,port) VALUES('%s','%s','%s',%d)", client->username, client->password, client->ip, client->port);
if (mysql_query(conn, sql) != 0) {
printf("Failed to insert into MySQL: %s\n", mysql_error(conn));
return 0;
}
return 1;
}
// 获取在线用户列表
int get_online_users(MYSQL* conn, char* list) {
char sql[BUFFER_SIZE];
sprintf(sql, "SELECT * FROM users WHERE status=1");
if (mysql_query(conn, sql) != 0) {
printf("Failed to query from MySQL: %s\n", mysql_error(conn));
return 0;
}
MYSQL_RES* res = mysql_store_result(conn);
int num_rows = mysql_num_rows(res);
MYSQL_ROW row;
for (int i = 0; i < num_rows; i++) {
row = mysql_fetch_row(res);
strcat(list, row[1]);
strcat(list, "\n");
}
mysql_free_result(res);
return num_rows;
}
// 保存聊天记录
int save_chat_record(MYSQL* conn, chat_record record) {
char sql[BUFFER_SIZE];
sprintf(sql, "INSERT INTO chat_history(sender,receiver,content,datetime) VALUES('%s','%s','%s','%s')", record.sender, record.receiver, record.content, record.datetime);
if (mysql_query(conn, sql) != 0) {
printf("Failed to insert into MySQL: %s\n", mysql_error(conn));
return 0;
}
return 1;
}
// 获取聊天记录
int get_chat_history(MYSQL* conn, char* sender, char* receiver, char* history) {
char sql[BUFFER_SIZE];
sprintf(sql, "SELECT * FROM chat_history WHERE (sender='%s' AND receiver='%s') OR (sender='%s' AND receiver='%s') ORDER BY id ASC", sender, receiver, receiver, sender);
if (mysql_query(conn, sql) != 0) {
printf("Failed to query from MySQL: %s\n", mysql_error(conn));
return 0;
}
MYSQL_RES* res = mysql_store_result(conn);
int num_rows = mysql_num_rows(res);
MYSQL_ROW row;
for (int i = 0; i < num_rows; i++) {
row = mysql_fetch_row(res);
sprintf(history, "%s[%s] %s: %s\n", history, row[4], row[1], row[3]);
}
mysql_free_result(res);
return num_rows;
}
// 处理连接请求
void handle_connection(tcp_info* tcp_clients, int* num_clients, MYSQL* conn) {
int iResult;
SOCKET listen_socket = tcp_clients[*num_clients].socket;
SOCKADDR_IN client_addr;
int client_addr_size = sizeof(client_addr);
SOCKET client_socket = accept(listen_socket, (SOCKADDR*)&client_addr, &client_addr_size);
if (client_socket == INVALID_SOCKET) {
printf("Failed to accept client socket: %d\n", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return;
}
char client_ip[16];
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip));
int client_port = ntohs(client_addr.sin_port);
printf("Client connected: %s:%d\n", client_ip, client_port);
tcp_clients[*num_clients].socket = client_socket;
strcpy(tcp_clients[*num_clients].ip, client_ip);
tcp_clients[*num_clients].port = client_port;
(*num_clients)++;
if (*num_clients >= MAX_CLIENTS) {
printf("Too many clients connected, closing the server.\n");
closesocket(listen_socket);
WSACleanup();
return;
}
char welcome_message[BUFFER_SIZE];
sprintf(welcome_message, "Welcome to the chatroom, your IP address is %s, your port number is %d.\n", client_ip, client_port);
send(client_socket, welcome_message, strlen(welcome_message), 0);
char buffer[BUFFER_SIZE];
char response[BUFFER_SIZE];
client_info client;
chat_record record;
char online_users[BUFFER_SIZE];
int recv_size;
while (1) {
memset(buffer, 0, sizeof(buffer));
recv_size = recv(client_socket, buffer, BUFFER_SIZE, 0);
if (recv_size == SOCKET_ERROR) {
printf("Failed to receive data: %d\n", WSAGetLastError());
break;
}
else if (recv_size == 0) {
printf("Client disconnected: %s:%d\n", client_ip, client_port);
break;
}
printf("Received data from client: %s:%d\n", client_ip, client_port);
printf("Data: %s\n", buffer);
if (strstr(buffer, "login") != NULL) {
sscanf(buffer, "login %s %s", client.username, client.password);
strcpy(client.ip, client_ip);
client.port = client_port;
if (login(conn, &client)) {
sprintf(response, "Welcome back, %s.\n", client.username);
send(client_socket, response, strlen(response), 0);
sprintf(record.sender, "server");
strcpy(record.receiver, client.username);
strcpy(record.content, response);
sprintf(record.datetime, "%ld", time(NULL));
save_chat_record(conn, record);
}
else {
sprintf(response, "Invalid username or password.\n");
send(client_socket, response, strlen(response), 0);
}
}
else if (strstr(buffer, "register") != NULL) {
sscanf(buffer, "register %s %s", client.username, client.password);
strcpy(client.ip, client_ip);
client.port = client_port;
if (register_user(conn, &client)) {
sprintf(response, "Register successful, %s.\n", client.username);
send(client_socket, response, strlen(response), 0);
sprintf(record.sender, "server");
strcpy(record.receiver, client.username);
strcpy(record.content, response);
sprintf(record.datetime, "%ld", time(NULL));
save_chat_record(conn, record);
}
else {
sprintf(response, "Failed to register, please try again later.\n");
send(client_socket, response, strlen(response), 0);
}
}
else if (strstr(buffer, "online") != NULL) {
int num_online_users = get_online_users(conn, online_users);
if (num_online_users > 0) {
sprintf(response, "Online users:\n%s", online_users);
send(client_socket, response, strlen(response), 0);
}
else {
sprintf(response, "No one is online.\n");
send(client_socket, response, strlen(response), 0);
}
}
else if (strstr(buffer, "chat") != NULL) {
char receiver[32];
char content[256];
sscanf(buffer, "chat %s %[^\n]", receiver, content);
sprintf(record.sender, "%s:%d", client_ip, client_port);
strcpy(record.receiver, receiver);
strcpy(record.content, content);
sprintf(record.datetime, "%ld", time(NULL));
save_chat_record(conn, record);
sprintf(response, "[%s] %s: %s\n", record.datetime, client.username, content);
send(client_socket, response, strlen(response), 0);
for (int i = 0; i < *num_clients; i++) {
if (i != *num_clients - 1 && strcmp(tcp_clients[i].ip, client_ip) == 0 && tcp_clients[i].port == client_port) {
continue;
}
sprintf(response, "[%s] %s: %s\n", record.datetime, client.username, content);
send(tcp_clients[i].socket, response, strlen(response), 0);
}
}
else if (strstr(buffer, "history") != NULL) {
char receiver[32];
char history[1024];
sscanf(buffer, "history %s", receiver);
int num_records = get_chat_history(conn, client.username, receiver, history);
if (num_records > 0) {
sprintf(response, "Chat history between you and %s:\n%s", receiver, history);
send(client_socket, response, strlen(response), 0);
}
else {
sprintf(response, "No chat history between you and %s.\n", receiver);
send(client_socket, response, strlen(response), 0);
}
}
else {
sprintf(response, "Unknown command.\n");
send(client_socket, response, strlen(response), 0);
}
}
closesocket(client_socket);
(*num_clients)--;
}
int main() {
int iResult;
WSADATA wsaData;
MYSQL* conn = NULL;
tcp_info tcp_clients[MAX_CLIENTS];
int num_clients = 0;
// 初始化Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("Failed to init Winsock: %d\n", iResult);
return 1;
}
// 创建TCP监听套接字
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_socket == INVALID_SOCKET) {
printf("Failed to create listen socket: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// 绑定监听套接字
SOCKADDR_IN server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
iResult = bind(listen_socket, (SOCKADDR*)&server_addr, sizeof(server_addr));
if (iResult == SOCKET_ERROR) {
printf("Failed to bind listen socket: %d\n", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return 1;
}
// 监听连接请求
iResult = listen(listen_socket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("Failed to listen on listen socket: %d\n", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return 1;
}
// 连接数据库
conn = connect_db();
if (conn == NULL) {
closesocket(listen_socket);
WSACleanup();
return 1;
}
printf("Server started, listening on port %d...\n", SERVER_PORT);
// 处理连接请求
while (1) {
handle_connection(tcp_clients, &num_clients, conn);
}
// 关闭数据库连接
close_db(conn);
// 关闭TCP监听套接字
closesocket(listen_socket);
// 释放Winsock资源
WSACleanup();
return 0;
}
```
阅读全文