基于udp的网络聊天室

一、基于udp的网络聊天室

1.服务器

#include <myhead.h>

#define SER_PORT 8888           // 服务器端口号
#define SER_IP "192.168.0.109" // 服务器ip地址
#define CLI_PORT 7777          // 客户端端口号
#define CLI_IP "192.168.0.128" // 客户端地址

enum type_t
{
    Login,    //登录
    Chat,     //输入
    Quit,    //退出
};

typedef struct MSG
{
    char type;  //内容编号
    char name[20];//名字
    char text[128];//内容
}msg_t;

typedef struct NODE
{
    struct sockaddr_in cin;
    struct NODE *next;
}Node,*Nodeptr;

// 创建节点
Nodeptr create()
{
    Nodeptr p = (Nodeptr)malloc(sizeof(Node));
    if (p == NULL)
    {
        perror("malloc error");
        return NULL;
    }
    p->next = NULL;
    return p;
}

int main(int argc, char const *argv[])
{
    // 创建套接字文件
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket error");
        return -1;
    } 
   
    //定义结构体 
    struct sockaddr_in sin;
    sin.sin_family=AF_INET;
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);
   
    // 保存客户端在结构体中
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(CLI_PORT);
    cin.sin_addr.s_addr = inet_addr(CLI_IP);
    socklen_t len = sizeof(cin);

    // 绑定
    bind(sockfd, (struct sockaddr *)&sin, sizeof(sin));
    printf("bind success\n");
    msg_t msg;
    Nodeptr p = create();//创建节点
    char s[128]="";

    while (1)
    {
        //接收客户端消息
        if (recvfrom(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, &len) < 0)
        {
            perror("recvfrom error");
            return -1;
        }

        if (msg.type == Login)
        {
            printf("客户端%s上线\n",msg.name);
            while (p->next != NULL)
            {
                p = p->next;
                sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
            }
            Nodeptr new = (Nodeptr)malloc(sizeof(Node));
            // 初始化
            new->cin = cin;
            new->next = NULL;
            // 链接到链表尾
            p->next = new;
        }
        else if (msg.type == Chat)
        {
                // 遍历链表
                while (p->next != NULL)
               {
                   p = p->next;
 
                   if (memcmp(&(p->cin), &cin,sizeof(cin))!= 0)
                   {
                       sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
                   }
              }
        }
        else if (msg.type == Quit)
        {
            printf("客户端已下线\n");
            while (p->next != NULL)
            {
                if (memcmp(&(p->cin), &cin,sizeof(cin)) == 0)
                {
                    Nodeptr q = NULL;
                    q = p->next;
                    p->next = q->next;
                    free(q);
                    q = NULL;
                }
                else
                {
                    p = p->next;
                    sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
                }
            }
        }
    }

    close(sockfd);
    return 0;
}
#include <myhead.h>

#define SER_PORT 8888           // 服务器端口号
#define SER_IP "192.168.0.109" // 服务器ip地址
#define CLI_PORT 7777          // 客户端端口号
#define CLI_IP "192.168.0.128" // 客户端地址

enum type_t
{
    Login,    //登录
    Chat,     //输入
    Quit,    //退出
};

typedef struct MSG
{
    char type;  //内容编号
    char name[20];//名字
    char text[128];//内容
}msg_t;

int main(int argc, char const *argv[])
{
    //创建套接字文件
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket error");
        exit(-1);
    }
    //创建信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);

    socklen_t len = sizeof(sin);
    msg_t msg;

    // 先执行登录操作
    msg.type = Login;
    printf("请输入用户名:");
    fgets(msg.name, 32, stdin);
    msg.name[strlen(msg.name) - 1] = 0;

    // 发送消息给服务端登录该客户端
    if (sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len) < 0)
    {
        perror("sendto err");
        return -1;
    }
    //创建子进程
    pid_t pid = fork();
    //父进程
    if (pid > 0)
    {
          while (1)
        {
            printf("请输入想输入的内容\n");
            fgets(msg.text, sizeof(msg.text), stdin);
            msg.text[strlen(msg.text) - 1] = 0;
            if (strcmp(msg.text, "quit") == 0)
            {
                msg.type = Quit;
                sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len);
                kill(pid, SIGKILL);
                wait(1);
                exit(EXIT_SUCCESS);
            }
            else
            {
                msg.type = Chat;
            }
            // 发送消息
            sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len);
        }
    }
    //子进程
    else if (pid == 0)
    {
        while (1)
        {
            //向自己发送消息
            if (recvfrom(sockfd, &msg, sizeof(msg), 0, NULL, NULL) < 0)
            {
                perror("recvfrom error");
                return -1;
            }
            printf("[%s]:%s\n", msg.name, msg.text);
        }
    }
    
    else
    {
        perror("fork error");
        return -1;
    }
    //关闭套接字文件
    close(sockfd);
    return 0;

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值