衡水做网站推广找谁,专门做护肤品的网站是,企业网站用什么做,收录优美图片找不到了一.项目需求#xff1a; 如果有用户登录#xff0c;其他用户可以收到这个人的登录信息如果有人发送信息#xff0c;其他用户可以收到这个人的群聊信息如果有人下线#xff0c;其他用户可以收到这个人的下线信息服务器可以发送系统信息 二.服务器端
#include myhead.h 如果有用户登录其他用户可以收到这个人的登录信息如果有人发送信息其他用户可以收到这个人的群聊信息如果有人下线其他用户可以收到这个人的下线信息服务器可以发送系统信息 二.服务器端
#include myhead.h //服务器
#define SER_IP 192.168.125.48
#define SER_PORT 8888
#define MAX_CLIENTS 100
#define BUFFER_SIZE 1024typedef struct Node {struct sockaddr_in addr;char username[20];struct Node *next;
} Node, *List;typedef struct Msg {char type; // L 登陆模式, M 消息模式, Q 下线模式, S 系统消息char username[20];char message[BUFFER_SIZE];
} Message;List client_list NULL;// 添加客户端
void add_client(struct sockaddr_in *addr, const char *username) {Node *node malloc(sizeof(Node));memcpy((node-addr), addr, sizeof(struct sockaddr_in));strncpy(node-username, username, 19);node-next client_list;client_list node;
}// 移除客户端
void remove_client(Node *node) {Node **prev client_list;while (*prev *prev ! node) {prev (*prev)-next;}if (*prev) {Node *temp *prev;*prev node-next;free(temp);}
}// 广播消息
void broadcast_message(int sfd, const Message *msg,struct sockaddr_in *except_addr) {Node *current client_list;Message to_send *msg;to_send.message[sizeof(to_send.message) - 1] \0; // 确保消息字符串以null终止while (current) {if (memcmp((current-addr), except_addr, sizeof(struct sockaddr_in)) !0) {sendto(sfd, (const char *)to_send, sizeof(Message), 0,(struct sockaddr *)(current-addr),sizeof(struct sockaddr_in));}current current-next;}
}// 查找客户端
Node *find_client_by_addr(struct sockaddr_in *addr) {Node *current client_list;while (current) {if (memcmp((current-addr), addr, sizeof(struct sockaddr_in)) 0) {return current;}current current-next;}return NULL;
}int main() {int sfd socket(AF_INET, SOCK_DGRAM, 0);if (sfd 0) {perror(socket creation failed);exit(EXIT_FAILURE);}int reuse 1;if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, reuse, sizeof(reuse)) -1) {perror(setsockopt error);return -1;}struct sockaddr_in server_addr, client_addr;server_addr.sin_family AF_INET;server_addr.sin_addr.s_addr inet_addr(SER_IP);server_addr.sin_port htons(SER_PORT);if (bind(sfd, (const struct sockaddr *)server_addr, sizeof(server_addr)) 0) {perror(bind failed);exit(EXIT_FAILURE);}printf(************服务器**************\n);printf(**********等待客户端**************\n);char buffer[BUFFER_SIZE] {0};struct timeval tv;fd_set readfds;int max_fd sfd;tv.tv_sec 5;tv.tv_usec 0;while (1) {FD_ZERO(readfds);FD_SET(sfd, readfds);// 检查是否有新的客户端连接或消息int res select(max_fd 1, readfds, NULL, NULL, tv);if (res 0) {perror(select error);break;} else if (res 0) {if (FD_ISSET(sfd, readfds)) {socklen_t client_len sizeof(client_addr);int n recvfrom(sfd, buffer, BUFFER_SIZE, 0,(struct sockaddr *)client_addr, client_len);if (n 0) {perror(recvfrom error);continue;}buffer[n] \0; // 确保字符串以null终止Message msg;memcpy(msg, buffer,(n sizeof(Message))? n: sizeof(Message)); // 防止缓冲区溢出switch (msg.type) {case L: // 客户端登录add_client(client_addr, msg.username);printf(%s 已登录\n, msg.username);// 广播登录信息给所有客户端除了发送者Message login_msg;strncpy(login_msg.username, msg.username, 19);login_msg.type L;login_msg.message[0] \0; // 清空消息字段因为是登录消息broadcast_message(sfd, login_msg, client_addr);break;case M: // 客户端发送消息printf(%s: %s\n, msg.username, msg.message);// 广播消息给所有客户端除了发送者broadcast_message(sfd, msg, client_addr);break;case Q: // 客户端退出{Node *node find_client_by_addr(client_addr);if (node) {printf(%s 已下线\n, node-username);Message quit_msg;strncpy(quit_msg.username, node-username, 19);quit_msg.type Q;quit_msg.message[0] \0; // 清空消息字段因为是下线消息remove_client(node);broadcast_message(sfd, quit_msg, client_addr);}} break;case S: // 服务器系统消息printf(系统消息: %s\n, msg.message);// 广播系统消息给所有客户端broadcast_message(sfd, msg, NULL);break;default:printf(未知的消息类型\n);break;}}}}close(sfd);return 0;
}三.客户端
#include myhead.h
#define SER_IP 192.168.125.48
#define SER_PORT 8888
#define BUFFER_SIZE 1024typedef struct Msg {char type; // L 登陆模式, M 消息模式, Q 下线模式, S 系统消息char username[20];char message[BUFFER_SIZE];
} Message;int main() {int sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0) {perror(socket creation failed);exit(EXIT_FAILURE);}struct sockaddr_in sin;memset(sin, 0, sizeof(sin));sin.sin_family AF_INET;sin.sin_addr.s_addr inet_addr(SER_IP);sin.sin_port htons(SER_PORT);char username[20];printf(输入您的名字: );scanf(%19s, username); // 限制输入长度为19个字符为null终止符留空间// 发送登录消息Message login_msg;login_msg.type L;strncpy(login_msg.username, username, sizeof(login_msg.username) - 1);login_msg.message[0] \0; // 清空消息字段因为是登录消息sendto(sockfd, login_msg, sizeof(login_msg), 0, (struct sockaddr *)sin,sizeof(sin));char message[BUFFER_SIZE];char recv_buffer[BUFFER_SIZE];struct sockaddr_in from_addr;socklen_t len sizeof(from_addr);while (1) {printf(输入消息 (or exit to quit): );if (scanf(%1023s, message) EOF || strcmp(message, exit) 0) {// 发送退出消息Message quit_msg;quit_msg.type Q;strncpy(quit_msg.username, username, sizeof(quit_msg.username) - 1);quit_msg.message[0] \0; // 清空消息字段因为是退出消息sendto(sockfd, quit_msg, sizeof(quit_msg), 0,(struct sockaddr *)sin, sizeof(sin));break;}while (getchar() ! \n); // 清除输入缓冲区中的换行符// 发送消息到服务器Message send_msg;send_msg.type M;strncpy(send_msg.username, username, sizeof(send_msg.username) - 1);strncpy(send_msg.message, message, sizeof(send_msg.message) - 1);send_msg.message[sizeof(send_msg.message) - 1] \0; // 确保消息字符串以null终止sendto(sockfd, send_msg, sizeof(send_msg), 0, (struct sockaddr *)sin,sizeof(sin));// 接收服务器的广播消息可能是其他客户端的消息或系统消息int n recvfrom(sockfd, recv_buffer, BUFFER_SIZE, 0,(struct sockaddr *)from_addr, len);if (n 0) {Message *msg (Message *)recv_buffer;recv_buffer[n] \0; // 确保字符串以null终止switch (msg-type) {case L: // 登录通知printf(%s 已登录\n, msg-username);break;case M: // 群聊消息printf(%s: %s\n, msg-username, msg-message);break;case Q: // 下线通知printf(%s 已下线\n, msg-username);break;case S: // 系统消息printf(系统消息: %s\n, msg-message);break;default:printf(未知的消息类型\n);break;}}}close(sockfd);return 0;
}不完善仅供参考