帮我用c++写windows下基于socket通信的聊天室服务器与客户端实现的代码 完成功能: 1.用户注册功能; 2.两个用户服务器发送私密消息; 3.用户创建一个或多个聊天群组; 4.用户加入群组、在群组内发送消息、离开群组; 5.用户之间的聊天信息通过服务器端转发;
时间: 2024-05-13 11:15:06 浏览: 76
C++聊天室Socket
以下是基于socket通信的聊天室服务器与客户端的代码,实现了功能:用户注册、私密消息发送、创建聊天群组、加入群组、在群组内发送消息、离开群组、用户之间的聊天信息通过服务器端转发。
服务器端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
#define BUF_SIZE 100
#define MAX_CLNT 256
void ErrorHandling(char *message);
typedef struct {
SOCKET socket;
struct sockaddr_in addr;
char name[20];
} client;
typedef struct {
int count;
client *clnt[MAX_CLNT];
} client_list;
client_list clnt_list = {0};
void send_message(char *message, int len, int sender, int receiver);
void send_message_all(char *message, int len, int sender);
int main(int argc, char *argv[]) {
WSADATA wsaData;
SOCKET serv_sock, clnt_sock;
SOCKADDR_IN serv_addr, clnt_addr;
int clnt_addr_size;
char message[BUF_SIZE];
int str_len, i;
if (argc != 2) {
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
ErrorHandling("WSAStartup() error!");
}
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if (serv_sock == INVALID_SOCKET) {
ErrorHandling("socket() error!");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1]));
if (bind(serv_sock, (SOCKADDR*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
ErrorHandling("bind() error!");
}
if (listen(serv_sock, MAX_CLNT) == SOCKET_ERROR) {
ErrorHandling("listen() error!");
}
while (1) {
clnt_addr_size = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (SOCKADDR*)&clnt_addr, &clnt_addr_size);
if (clnt_sock == INVALID_SOCKET) {
continue;
}
client *new_client = (client*)malloc(sizeof(client));
new_client->socket = clnt_sock;
new_client->addr = clnt_addr;
memset(new_client->name, 0, sizeof(new_client->name));
clnt_list.clnt[clnt_list.count++] = new_client;
printf("new client connected, count=%d\n", clnt_list.count);
send_message_all("[Server] A new client connected.\n", 35, -1);
while ((str_len = recv(clnt_sock, message, BUF_SIZE, 0)) != 0) {
int index = -1;
for (i = 0; i < clnt_list.count; i++) {
if (clnt_list.clnt[i]->socket == clnt_sock) {
index = i;
break;
}
}
if (index == -1) {
break;
}
message[str_len] = '\0';
if (strlen(message) == 0) {
continue;
}
if (message[0] == '/') {
char command[BUF_SIZE];
int j = 1;
while (j < str_len && message[j] != ' ') {
command[j - 1] = message[j];
j++;
}
command[j - 1] = '\0';
if (strcmp(command, "name") == 0) {
char name[BUF_SIZE];
int k = j + 1;
while (k < str_len) {
name[k - j - 1] = message[k];
k++;
}
name[k - j - 1] = '\0';
strcpy(clnt_list.clnt[index]->name, name);
printf("client %s set name to %s\n", inet_ntoa(clnt_list.clnt[index]->addr.sin_addr), name);
send_message_all("[Server] A client set name.\n", 32, -1);
} else if (strcmp(command, "to") == 0) {
char name[BUF_SIZE];
int k = j + 1;
while (k < str_len && message[k] != ' ') {
name[k - j - 1] = message[k];
k++;
}
name[k - j - 1] = '\0';
int receiver = -1;
for (i = 0; i < clnt_list.count; i++) {
if (strcmp(clnt_list.clnt[i]->name, name) == 0) {
receiver = i;
break;
}
}
if (receiver == -1) {
send_message("[Server] The client does not exist.\n", 38, -1, index);
} else {
send_message(message, str_len, index, receiver);
}
} else if (strcmp(command, "create") == 0) {
char name[BUF_SIZE];
int k = j + 1;
while (k < str_len) {
name[k - j - 1] = message[k];
k++;
}
name[k - j - 1] = '\0';
int flag = 0;
for (i = 0; i < clnt_list.count; i++) {
if (strcmp(clnt_list.clnt[i]->name, name) == 0) {
flag = 1;
break;
}
}
if (flag == 1) {
send_message("[Server] The group name already exists.\n", 44, -1, index);
} else {
client *new_client = (client*)malloc(sizeof(client));
new_client->socket = -2;
memset(new_client->name, 0, sizeof(new_client->name));
clnt_list.clnt[clnt_list.count++] = new_client;
strcpy(clnt_list.clnt[clnt_list.count - 1]->name, name);
printf("client %s create group %s\n", inet_ntoa(clnt_list.clnt[index]->addr.sin_addr), name);
send_message_all("[Server] A client create group.\n", 34, -1);
send_message("[Server] The group created successfully.\n", 44, -1, index);
}
} else if (strcmp(command, "join") == 0) {
char name[BUF_SIZE];
int k = j + 1;
while (k < str_len) {
name[k - j - 1] = message[k];
k++;
}
name[k - j - 1] = '\0';
int group = -1;
for (i = 0; i < clnt_list.count; i++) {
if (strcmp(clnt_list.clnt[i]->name, name) == 0 && clnt_list.clnt[i]->socket == -2) {
group = i;
break;
}
}
if (group == -1) {
send_message("[Server] The group does not exist.\n", 38, -1, index);
} else {
clnt_list.clnt[index]->socket = -3;
send_message("[Server] You have joined the group.\n", 38, -1, index);
send_message_all("[Server] A client joined the group.\n", 36, -1);
send_message("[Server] You can now send messages in the group.\n", 53, -1, index);
}
} else if (strcmp(command, "leave") == 0) {
if (clnt_list.clnt[index]->socket != -3) {
send_message("[Server] You are not in a group.\n", 35, -1, index);
} else {
clnt_list.clnt[index]->socket = clnt_sock;
send_message("[Server] You left the group.\n", 32, -1, index);
send_message_all("[Server] A client left the group.\n", 35, -1);
}
} else if (strcmp(command, "list") == 0) {
char list[BUF_SIZE];
memset(list, 0, sizeof(list));
for (i = 0; i < clnt_list.count; i++) {
if (clnt_list.clnt[i]->socket == -2) {
strcat(list, clnt_list.clnt[i]->name);
strcat(list, " ");
}
}
strcat(list, "\n");
send_message(list, strlen(list), -1, index);
} else if (strcmp(command, "members") == 0) {
if (clnt_list.clnt[index]->socket != -3) {
send_message("[Server] You are not in a group.\n", 35, -1, index);
} else {
char members[BUF_SIZE];
memset(members, 0, sizeof(members));
for (i = 0; i < clnt_list.count; i++) {
if (clnt_list.clnt[i]->socket == -3) {
strcat(members, clnt_list.clnt[i]->name);
strcat(members, " ");
}
}
strcat(members, "\n");
send_message(members, strlen(members), -1, index);
}
} else {
send_message("[Server] Invalid command.\n", 28, -1, index);
}
} else {
if (clnt_list.clnt[index]->socket == -3) {
send_message_all(message, str_len, index);
} else {
send_message_all(message, str_len, index);
}
}
}
for (i = 0; i < clnt_list.count; i++) {
if (clnt_list.clnt[i]->socket == clnt_sock) {
printf("client %s disconnected\n", inet_ntoa(clnt_list.clnt[i]->addr.sin_addr));
send_message_all("[Server] A client disconnected.\n", 36, -1);
int j;
for (j = i; j < clnt_list.count - 1; j++) {
clnt_list.clnt[j] = clnt_list.clnt[j + 1];
}
clnt_list.count--;
break;
}
}
closesocket(clnt_sock);
}
closesocket(serv_sock);
WSACleanup();
return 0;
}
void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
void send_message(char *message, int len, int sender, int receiver) {
if (receiver < 0 || receiver >= clnt_list.count) {
return;
}
send(clnt_list.clnt[receiver]->socket, message, len, 0);
if (sender >= 0 && sender < clnt_list.count) {
printf("client %s send message to %s: %s", inet_ntoa(clnt_list.clnt[sender]->addr.sin_addr), inet_ntoa(clnt_list.clnt[receiver]->addr.sin_addr), message);
}
}
void send_message_all(char *message, int len, int sender) {
int i;
for (i = 0; i < clnt_list.count; i++) {
if (sender == i) {
continue;
}
send(clnt_list.clnt[i]->socket, message, len, 0);
}
if (sender >= 0 && sender < clnt_list.count) {
printf("client %s send message to all: %s", inet_ntoa(clnt_list.clnt[sender]->addr.sin_addr), message);
}
}
```
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>
#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
#define BUF_SIZE 100
void ErrorHandling(char *message);
void menu();
void register_user(SOCKET hSocket);
void set_name(SOCKET hSocket);
void send_message(SOCKET hSocket);
void send_private_message(SOCKET hSocket);
void create_group(SOCKET hSocket);
void join_group(SOCKET hSocket);
void leave_group(SOCKET hSocket);
void list_group(SOCKET hSocket);
void list_members(SOCKET hSocket);
int main(int argc, char *argv[]) {
WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN serv_addr;
char message[BUF_SIZE];
int str_len;
if (argc != 3) {
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
ErrorHandling("WSAStartup() error!");
}
hSocket = socket(PF_INET, SOCK_STREAM, 0);
if (hSocket == INVALID_SOCKET) {
ErrorHandling("socket() error!");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(atoi(argv[2]));
if (connect(hSocket, (SOCKADDR*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
ErrorHandling("connect() error!");
}
menu();
while (1) {
char choice = getch();
switch (choice) {
case '1':
register_user(hSocket);
break;
case '2':
set_name(hSocket);
break;
case '3':
send_message(hSocket);
break;
case '4':
send_private_message(hSocket);
break;
case '5':
create_group(hSocket);
break;
case '6':
join_group(hSocket);
break;
case '7':
leave_group(hSocket);
break;
case '8':
list_group(hSocket);
break;
case '9':
list_members(hSocket);
break;
case '0':
closesocket(hSocket);
WSACleanup();
return 0;
default:
printf("Invalid choice.\n");
break;
}
menu();
}
closesocket(hSocket);
WSACleanup();
return 0;
}
void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
void menu() {
system("cls");
printf("=========================================\n");
printf("1. Register\n");
printf("2. Set name\n");
printf("3. Send message to all\n");
printf("4. Send private message\n");
printf("5. Create group\n");
printf("6. Join group\n");
printf("7. Leave group\n");
printf("8. List groups\n");
printf("9. List members\n");
printf("0. Exit\n");
printf("=========================================\n");
}
void register_user(SOCKET hSocket) {
char message[BUF_SIZE];
printf("Enter username (max 19 characters): ");
fgets(message, BUF_SIZE, stdin);
message[strlen(message) - 1] = '\0';
send(hSocket, message, strlen(message), 0);
recv(hSocket, message, BUF_SIZE, 0);
printf("%s\n", message);
}
void set_name(SOCKET hSocket) {
char message[BUF_SIZE];
printf("Enter your name (max 19 characters): ");
fgets(message, BUF_SIZE, stdin);
message[strlen(message) - 1] = '\0';
sprintf(message, "/name %s", message);
send(hSocket, message, strlen(message), 0);
}
void send_message(SOCKET hSocket) {
char message[BUF_SIZE];
printf("Enter message: ");
fgets(message, BUF_SIZE, stdin);
send(hSocket, message, strlen(message), 0);
}
void send_private_message(SOCKET hSocket) {
char name[20], message[BUF_SIZE];
printf("Enter receiver's name (max 19 characters): ");
fgets(name, 20, stdin);
name[strlen(name) - 1] = '\0';
printf("Enter message: ");
fgets(message, BUF_SIZE, stdin);
sprintf(message, "/to %s %s", name, message);
send(hSocket, message, strlen(message), 0);
}
void create_group(SOCKET hSocket) {
char name[20], message[BUF_SIZE];
printf("Enter group name (max 19 characters): ");
fgets(name, 20, stdin);
name[strlen(name) - 1] = '\0';
sprintf(message, "/create %s", name);
send(hSocket, message, strlen(message), 0);
recv(hSocket, message, BUF_SIZE, 0);
printf("%s\n", message);
}
void join_group(SOCKET hSocket) {
char name[20], message[BUF_SIZE];
printf("Enter group name (max 19 characters): ");
fgets(name, 20, stdin);
name[strlen(name) - 1] = '\0';
sprintf(message, "/join %s", name);
send(hSocket, message, strlen(message), 0);
recv(hSocket, message, BUF_SIZE, 0);
printf("%s\n", message);
}
void leave_group(SOCKET hSocket) {
char message[BUF_SIZE];
sprintf(message, "/leave");
send(hSocket, message, strlen(message), 0);
recv(hSocket, message, BUF_SIZE, 0);
printf("%s\n
阅读全文