博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux网络编程 UDP聊天程序 包括群聊和私聊
阅读量:4072 次
发布时间:2019-05-25

本文共 13540 字,大约阅读时间需要 45 分钟。

原文地址:

程序功能:

   能够支持多个客户端同时运行,具有群聊,私聊,上线通知,下线通知,系统消息等功能。

程序如下:

1. server.c

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define CLIENT_LOGIN    100#define CLIENT_CHAT     200#define CLIENT_QUIT     300#define SERVER_CHAT     400#define SERVER_QUIT     500#define PRINT_ONLINE    600#define PRIVATE_CHAT    700struct node {    char name[20];    struct sockaddr_in client_addr;    struct node *next;};struct message{    long type;    char name[20];    char peer_name[20];    char mtext[512];};struct node *create_list(void);void insert_list(struct node *, char *,struct sockaddr_in *);void delete_list(struct node *, char *);void recv_message(int , struct node *);void send_message(int , struct sockaddr_in *, pid_t );void client_login(int , struct node *, struct message *, struct sockaddr_in *);void client_chat(int , struct node *, struct message *);void client_quit(int , struct node *, struct message *);void server_chat(int , struct node *, struct message *);void server_quit(int , struct node *, struct message *);void brocast_msg(int , struct node *, struct message *);void print_online(int , struct node *, struct message *);void private_chat(int , struct node *, struct message *);void father_func(int sig_no){    return ;}int main(int argc, const char *argv[]){    int socket_fd;    pid_t pid;    struct sockaddr_in server_addr;    struct node *head;    if (argc < 3)    {        fprintf(stderr, "usages : %s ip port\n", argv[0]);        exit(-1);    }    if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)    {        perror("failed to create socket");        exit(-1);    }    head = create_list();    server_addr.sin_family = AF_INET;    server_addr.sin_port = htons(atoi(argv[2]));    server_addr.sin_addr.s_addr = inet_addr(argv[1]);    if (bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)    {        perror("failed to bind");        exit(-1);    }    if ((pid = fork()) < 0)    {        perror("failed to fork pid");        exit(-1);    }    if (pid == 0)        recv_message(socket_fd, head);    else        send_message(socket_fd, &server_addr, pid);    return 0;}struct node *create_list(void){    struct node *head;    head = (struct node *)malloc(sizeof(struct node));    head->next = NULL;    return head;}void insert_list(struct node *head, char *name, struct sockaddr_in *client_addr){    struct node *new;    new = (struct node *)malloc(sizeof(struct node));    strcpy(new->name, name);    new->client_addr = *client_addr;    new->next = head->next;    head->next = new;    return ;}void delete_list(struct node *head, char *name){    struct node *p = head->next;    struct node *q = head;    while (p != NULL)    {        if (strcmp(p->name, name) == 0)            break;        p = p->next;        q = q->next;    }    q->next = p->next;    p->next = NULL;    free(p);    return ;}void recv_message(int socket_fd, struct node *head){    struct message msg;    struct sockaddr_in client_addr;    int client_addrlen = sizeof(struct sockaddr);    while (1)    {        memset(&msg, 0, sizeof(msg));        if (recvfrom(socket_fd, &msg, sizeof(msg), 0, (struct sockaddr *)&client_addr, &client_addrlen) < 0)        {            perror("failed to recvform client");            exit(-1);        }        switch(msg.type)        {            case CLIENT_LOGIN:                client_login(socket_fd, head, &msg, &client_addr);                break;            case CLIENT_CHAT:                client_chat(socket_fd, head, &msg);                break;            case CLIENT_QUIT:                client_quit(socket_fd, head, &msg);                break;            case SERVER_CHAT:                server_chat(socket_fd, head, &msg);                break;            case SERVER_QUIT:                server_quit(socket_fd, head, &msg);                break;            case PRINT_ONLINE:                print_online(socket_fd, head, &msg);                break;            case PRIVATE_CHAT:                private_chat(socket_fd, head, &msg);                break;            default:                break;        }    }    return ;}void send_message(int socket_fd, struct sockaddr_in *server_addr, pid_t pid){    struct message msg;    char buf[512];    signal(getppid(), father_func);        while (1)    {        usleep(500);        printf(">");        fgets(buf, sizeof(buf), stdin);        buf[strlen(buf) - 1] = 0;        strcpy(msg.mtext, buf);        strcpy(msg.name , "server");        msg.type = SERVER_CHAT;        if (strncmp(buf, "quit", 4) == 0)        {            msg.type = SERVER_QUIT;            if (sendto(socket_fd, &msg, sizeof(msg), 0,                         (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0)            {                perror("failed to send server_quit message");                exit(-1);            }            pause();            kill(pid, SIGKILL);            waitpid(pid, NULL, 0);            close(socket_fd);            exit(0);        }        if (sendto(socket_fd, &msg, sizeof(msg), 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0)        {            perror("failed to send server_chat message");            exit(-1);        }    }    return ;}void client_login(int socket_fd, struct node *head, struct message *msg, struct sockaddr_in *client_addr){    printf("********Login In********\n");    printf("%s is Login In\n", msg->name);    printf("************************\n");    insert_list(head, msg->name, client_addr);    brocast_msg(socket_fd, head, msg);    return ;}void client_chat(int socket_fd, struct node *head, struct message *msg){    printf("********Group Chat********\n");    printf("name: %s\n", msg->name);    printf("msg: %s\n", msg->mtext);    printf("**************************\n");    brocast_msg(socket_fd, head, msg);    return ;}void client_quit(int socket_fd, struct node *head, struct message *msg){    printf("*********Quit Msg********\n");    printf("%s is Quit\n", msg->name);    printf("*************************\n");    delete_list(head, msg->name);    brocast_msg(socket_fd, head, msg);    return ;}void server_chat(int socket_fd, struct node *head, struct message *msg){    printf("********Server Msg*********\n");    printf("msg: %s\n", msg->mtext);    printf("***************************\n");    brocast_msg(socket_fd, head, msg);    return ;}void server_quit(int socket_fd, struct node *head, struct message *msg){    brocast_msg(socket_fd, head, msg);    kill(getppid(), SIGUSR1);    return ;}void print_online(int socket_fd, struct node *head, struct message *msg){    struct node *p = head->next;    struct sockaddr_in my_addr;    char buf[512];    printf("%s is request to print online client\n", msg->name);    memset(buf, 0, sizeof(buf));    while (p != NULL)    {        if (strcmp(p->name, msg->name) == 0)            my_addr = p->client_addr;        strcat(buf, p->name);        strcat(buf, " ");                p = p->next;    }    strcpy(msg->mtext, buf);    msg->type = PRINT_ONLINE;    if (sendto(socket_fd, msg, sizeof(struct message), 0,                 (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)    {        perror("failed to send print_online message");        exit(-1);    }    return ;}void private_chat(int socket_fd, struct node *head, struct message *msg){    struct node *p = head->next;    struct sockaddr_in peer_addr;    printf("******** Private Msg ********\n");    printf("from %s\n", msg->name);    printf("to %s\n", msg->peer_name);    printf("msg: %s\n", msg->mtext);    printf("*****************************\n");    while (p != NULL)    {        if (strcmp(p->name, msg->peer_name) == 0)        {            peer_addr = p->client_addr;            break;        }        p = p->next;    }    if (sendto(socket_fd, msg, sizeof(struct message), 0,                 (struct sockaddr *)&peer_addr, sizeof(peer_addr)) < 0)    {        perror("failed to send private message");        exit(-1);    }    return ;}void brocast_msg(int socket_fd, struct node *head, struct message *msg){    struct node *p = head->next;    while(p != NULL)    {        if (msg->type == CLIENT_LOGIN)        {            if (strcmp(p->name, msg->name) == 0)            {                p = p->next;                continue;            }        }        sendto(socket_fd, msg, sizeof(struct message), 0, (struct sockaddr *)&(p->client_addr), sizeof(struct sockaddr));        p = p->next;    }    return ;}
2.client.c

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define CLIENT_LOGIN 100#define CLIENT_CHAT 200#define CLIENT_QUIT 300#define SERVER_CHAT 400#define SERVER_QUIT 500#define PRINT_ONLINE 600#define PRIVATE_CHAT 700struct message{ long type; char name[20]; char peer_name[20]; char mtext[512];};void recv_message(int );void send_message(int , struct sockaddr_in *, char *, pid_t);void login_msg(struct message *);void group_msg(struct message *);void quit_msg(struct message *);void server_msg(struct message *);void server_quit(void);void online_msg(struct message *);void private_msg(struct message *);void print_online(int , struct message *, struct sockaddr_in *);void group_chat(int , struct message *, struct sockaddr_in *);void private_chat(int ,struct message *, struct sockaddr_in *);void client_quit(int , struct message *, struct sockaddr_in *, pid_t );int main(int argc, char *argv[]){ pid_t pid; int server_fd; struct sockaddr_in server_addr; if (argc < 4) { fprintf(stderr, "usages: %s ip port name\n", argv[0]); exit(-1); } if ((server_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("failed to create server_fd"); exit(-1); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(atoi(argv[2])); server_addr.sin_addr.s_addr = inet_addr(argv[1]);// inet_pton(AF_INET,argv[1],&server_addr.sin_addr); //ipv4 if ((pid = fork()) < 0) { perror("failed to fork pid"); exit(-1); } if (pid == 0) recv_message(server_fd); else send_message(server_fd, &server_addr, argv[3], pid); return 0;}void recv_message(int server_fd){ struct message msg; while (1) { memset(&msg, 0, sizeof(msg)); if (recvfrom(server_fd, &msg, sizeof(msg), 0, NULL, NULL) < 0) { perror("failed to recv server message"); exit(-1); } switch(msg.type) { case CLIENT_LOGIN: login_msg(&msg); break; case CLIENT_CHAT: group_msg(&msg); break; case CLIENT_QUIT: quit_msg(&msg); break; case SERVER_CHAT: server_msg(&msg); break; case SERVER_QUIT: server_quit(); break; case PRINT_ONLINE: online_msg(&msg); break; case PRIVATE_CHAT: private_msg(&msg); break; default: break; } } return ;}void send_message(int server_fd, struct sockaddr_in *server_addr, char *name, pid_t pid){ struct message msg; char buf[512]; int c; msg.type = CLIENT_LOGIN; strcpy(msg.name, name); if (sendto(server_fd, &msg, sizeof(msg), 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) { perror("failed to send login message"); exit(-1); } while(1) { usleep(500); printf("#####################################\n"); printf("the following options can be choose:\n"); printf("input 1 is to print online client\n"); printf("input 2 is to chat to all the client\n"); printf("input 3 is to chat to only one client\n"); printf("input q is to quit\n"); printf("#####################################\n"); printf(">"); c = getchar(); //输入回车符时停止输入到缓冲区 while (getchar() != '\n'); //读出全部缓冲区的数据,包括'\n' switch(c) { case '1': print_online(server_fd, &msg, server_addr); break; case '2': group_chat(server_fd, &msg, server_addr); break; case '3': private_chat(server_fd, &msg, server_addr); break; case 'q': client_quit(server_fd, &msg, server_addr, pid); break; default: break; } } return ;}void login_msg(struct message *msg){ printf("######## Login in ########\n"); printf("%s is login in\n", msg->name); printf("######## Login in ########\n"); return ;}void group_msg(struct message *msg){ printf("******** Group Msg ********\n"); printf("name: %s\n", msg->name); printf("msg: %s\n", msg->mtext); printf("******** Group Msg ********\n"); return ;}void quit_msg(struct message *msg){ printf("######## Quit Msg ########\n"); printf("%s is Quit\n", msg->name); printf("######## Quit Msg ########\n"); return ;}void server_msg(struct message *msg){ printf("******** Server Msg ********\n"); printf("msg: %s\n", msg->mtext); printf("******** Server Msg ********\n"); return ;}void server_quit(void ){ kill(getppid(), SIGKILL); exit(0);}void online_msg(struct message *msg){ printf("******** Online Client ********\n"); printf("%s\n", msg->mtext); printf("******** Online Client ********\n"); return ;}void private_msg(struct message *msg){ printf("******** Private Msg ********\n"); printf("name: %s\n", msg->name); printf("msg: %s\n", msg->mtext); printf("******** Private Msg ********\n"); return ;}void print_online(int server_fd, struct message *msg, struct sockaddr_in *server_addr){ msg->type = PRINT_ONLINE; if (sendto(server_fd, msg, sizeof(struct message), 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) { perror("failed to send online message"); exit(-1); } return ;}void group_chat(int server_fd, struct message *msg, struct sockaddr_in *server_addr){ char buf[512]; memset(buf, 0, sizeof(buf)); printf("*********** Group Chat Room ***********\n"); printf("****** Welcome to group chat room ******\n"); printf("* if you want to quit, please input quit\n"); printf("****************************************\n"); while(1) { memset(buf, 0, sizeof(buf)); usleep(500); printf(">"); fgets(buf, sizeof(buf), stdin); buf[strlen(buf) - 1] = 0; msg->type = CLIENT_CHAT; strcpy(msg->mtext, buf); if (strncmp(buf, "quit", 4) == 0) break; if (sendto(server_fd, msg, sizeof(struct message), 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) { perror("failed to send group message"); exit(-1); } } return ;}void private_chat(int server_fd, struct message *msg, struct sockaddr_in *server_addr){ char name[20]; char buf[512]; memset(name, 0, sizeof(name)); printf("please input the peer_name\n"); printf(">"); fgets(name, sizeof(name), stdin); name[strlen(name) - 1] = 0; strcpy(msg->peer_name, name); msg->type = PRIVATE_CHAT; printf("connect to %s OK!\n", msg->peer_name); while(1) { usleep(500); printf(">"); fgets(buf, sizeof(buf), stdin); buf[strlen(buf) - 1] = 0; strcpy(msg->mtext, buf); if (strncmp(buf, "quit", 4) == 0) break; if (sendto(server_fd, msg, sizeof(struct message), 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) { perror("failed to send private message"); exit(-1); } } return ;}void client_quit(int server_fd, struct message *msg, struct sockaddr_in *server_addr, pid_t pid){ msg->type = CLIENT_QUIT; if (sendto(server_fd, msg, sizeof(struct message), 0, (struct sockaddr *)server_addr, sizeof(struct sockaddr)) < 0) { perror("failed to send quit message"); exit(-1); } kill(pid, SIGKILL); waitpid(pid, NULL, 0); exit(0);}

转载地址:http://wfgji.baihongyu.com/

你可能感兴趣的文章
iOS开发中一些常见的并行处理
查看>>
iOS获取手机的Mac地址
查看>>
ios7.1发布企业证书测试包的问题
查看>>
如何自定义iOS中的控件
查看>>
iOS 开发百问
查看>>
Mac环境下svn的使用
查看>>
github简单使用教程
查看>>
如何高效利用GitHub
查看>>
环境分支-git版本管理
查看>>
uni-app 全局变量
查看>>
js判断空对象的几种方法
查看>>
java 不用递归写tree
查看>>
springboot2 集成Hibernate JPA 用 声明式事物
查看>>
fhs-framework jetcache 缓存维护之自动清除缓存
查看>>
SpringBoot 动态编译 JAVA class 解决 jar in jar 的依赖问题
查看>>
fhs-framework springboot mybatis 解决表关联查询问题的关键方案-翻译服务
查看>>
ZUUL2 使用场景
查看>>
Spring AOP + Redis + 注解实现redis 分布式锁
查看>>
elastic-job 和springboot 集成干货
查看>>
php开发微服务注册到eureka中(使用sidecar)
查看>>