首页 > 其他分享 >坐牢第二十七天(聊天室)

坐牢第二十七天(聊天室)

时间:2024-08-16 16:26:21浏览次数:7  
标签:聊天室 struct 第二十七 cin 坐牢 sockfd msg sizeof sin

基于UDP的网络聊天室

一.项目需求:

1.如果有用户登录,其他用户可以收到这个人的登录信息

2.如果有人发送信息,其他用户可以收到这个人的群聊信息

3.如果有人下线,其他用户可以收到这个人的下线信息

4.服务器可以发送系统信息

二.代码 

udp.h

#ifndef UDP_H
#define UDP_H
#include <myhead.h>
#define SER_PORT 8888           // 服务器端口号
#define SER_IP "192.168.0.105" // 服务器ip地址
#define CLI_PORT 5555          // 客户端端口号
#define CLI_IP "192.168.0.105" // 客户端地址
//枚举
enum type_t
{
    Login,
    Chat,
    Quit,
};
typedef struct MSG
{
    char type;//Login名字  Chat内容 Quit退出  //内容编号
    char name[32];//名字
    char text[128];//内容
}msg_t;
typedef struct NODE//链表
{
    struct sockaddr_in cin;
    struct NODE *next;
}Node,*Nodeptr;
//创建头节点函数
Nodeptr create();
//登录的函数
//功能:
//1.将新登录的用户转发给所有已经登录的用户(遍历链表发送谁登录的消息)
//2.创建新节点来保存新登录用户的信息,链接到链表尾就可以
void do_login(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
//群聊的函数
//功能:将客户端发来的聊天内容转发给所有已登录的用户,除了发送聊天内容的用户以外
void do_chat(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
//退出函数
//功能:
//1.将谁退出的消息转发给i所有用户
//2.将链表中保存这个推出的用户信息的节点删除
void do_quit(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
#endif 

udp.c

#include "udp.h"
// 定义创建头节点函数
Nodeptr create()
{
    Nodeptr p = (Nodeptr)malloc(sizeof(Node));
    if (p == NULL)
    {
        perror("malloc error");
        return NULL;
    }
    p->next = NULL;
    return p;
}
// 定义登录的函数
void do_login(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
{
    sprintf(msg.text, "%s 以上线", 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;
    return;
}
// 定义群聊的函数
void do_chat(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
{
    // 遍历链表
    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));
        }
    }
    return;
}
// 定义退出函数
void do_quit(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
{
    sprintf(msg.text, "%s 以下线", msg.name);
    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));
        }
    }
    return;
}

sen.c

// 服务器
#include "udp.h"
int main(int argc, char const *argv[])
{
    // 创建UDP套接字
    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);
   
    // 定义保存客户端网络信息的结构体
    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("绑定成功!\n");
    msg_t msg;
    Nodeptr p = create();
    char s[20]="";
    while (1)
    {
        if (recvfrom(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, &len) < 0)
        {
            perror("recvfrom error");
            return -1;
        }
        if (msg.type == Login)
        {
            strcpy(msg.text, "以上线");
            printf("ip:%s pord:%d name:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.name);
            printf("状态:%s\n", msg.text);
            //调用登录函数
            do_login(sockfd, msg, p, cin);
        }
        else if (msg.type == Chat)
        {
            //调用群聊函数
            do_chat(sockfd, msg, p, cin);
        }
        else if (msg.type == Quit)
        {
            strcpy(msg.text, "以下线");
            printf("ip:%s pord:%d name:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.name);
            printf("状态:%s\n", msg.text);
            //调用退出函数
            do_quit(sockfd, msg, p, cin);
        }
    }
    close(sockfd);
    return 0;
}

rec.c

// 客户端
#include "udp.h"
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;
    // 先执行登录操作
    printf("请登录:\n");
    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");
        exit(-1);
    }
    //创建多进程
    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork error");
        exit(-1);
    }
    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
    {
        while (1)
        {
            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(NULL);
                exit(EXIT_SUCCESS);
            }
            else
            {
                msg.type = Chat;
            }
            // 发送消息
            sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len);
        }
    }
    close(sockfd);
    return 0;
}

标签:聊天室,struct,第二十七,cin,坐牢,sockfd,msg,sizeof,sin
From: https://blog.csdn.net/m0_62828714/article/details/141263125

相关文章

  • Java 基于微信小程序的学校心理咨询聊天室系统 uniapp毕业设计
    文末获取资源,收藏关注不迷路文章目录项目介绍功能需求技术介绍项目界面关键代码目录项目介绍该课题旨在创建一个专门针对大学生心理健康的知识科普平台,其受众包含大学生与其父母,包含知识科普,自我筛查,在线咨询,与匿名倾诉(包含父母与大学生)四个大点。全方位的对大学生......
  • 代码随想录算法训练营第二十七天| 56. 合并区间、738.单调递增的数字
    写代码的第二十七天最后一天贪心!!!加油呀!!!56.合并区间思路这道题本质上和昨天的两道题是几乎完全一致的,都是判断重叠区间,只不过昨天的射箭那道题是统计有多少重叠区间,无重叠区间那道题是找到重叠区间然后删除,这道题是找到重叠区间然后合并。解决问题1:如何对重叠区间进行......
  • 坐牢二十天 20240731(IO)
    一.作业1>使用父子进程完成两个文件的拷贝父进程拷贝前一半内容,子进程拷贝后一半内容子进程结束后退出,父进程回收子进程的资源#include<myhead.h>//定义求源文件长度的函数intlenmain(constchar*src,constchar*dst){intfd1=0;//源文件intfd2=0;//目......
  • 坐牢+水平精进(?)小记
    坐标成都外国语中学初中部3栋140寝,距离出狱不足24h时撰写Day.0赶火车来成都咯,本来想去天府红,结果根本没时间。在火车上用DJI拍了个延时摄影,然后一直和别人聊天扰民,整个车厢我们最吵。带了4个类青轴,然后分给了同学玩,然后清脆“蝉鸣”充斥车厢。从火车站打车到成......
  • 坐牢第十六天 20240724
    笔记1.二叉树的补充1.1二叉树的创建shu.h​​​​​​​​​​#ifndefSHU_H#defineSHU_H#include<myhead.h>typedefchardatatype;//定义节点类型typedefstructNode{datatypedata;//数据域structNode*L;//左孩子指针structNode*R;//右孩子指......
  • 坐牢第十五天 20240723
    一.笔记1.栈的补充 链式栈1>链式存储的栈,称为链式栈2>对于单链表而言,我们可以使用,使用头插头删完成一个栈,或者尾插尾删完成链式栈3>头插头删:链表的头部就是栈顶,链表的尾部就是栈底(常用)4>尾插尾删:链表的尾部就是栈顶,链表的头部就是栈底2.队列2.1队列介绍1>队列......
  • 坐牢第十三天 20240719
    一.笔记一.链表的引入1.1总结顺序表的优缺点1>优点:能够直接通过下标进行定位元素,访问效率高,对元素进行查找和修改比较快2>不足:插入和删除元素需要移动大量的元素,效率较低3>缺点:存储数据元素有上限,当达到MAX后,就不能再添加元素了1.2链表的概念1>链式存储的线性表叫......
  • Qt项目:基于Qt实现的网络聊天室---好友申请
    文章目录完善ClickedLabel好友申请美化界面本文介绍如何实现好友申请界面,其效果如下图所示在此之前需要先定义一个ClickedOnceLabel类,支持点击一次的label功能。接着新增一个ClickedOnceLabel类classClickedOnceLabel:publicQLabel{Q_OBJECTpublic:......
  • thinkPHP+swoole扩展搭建一个websocket连接聊天室(简易版)
    1.服务器搭建好宝塔面板,并开放用于连接websocket的端口:例如9502 2.本地准备好连接的文件,以thinkPHP举例:(1)根目录下的Websocket.php文件(2)前端index入口文件添加test()方法,然后在view目录里添加相应的test.html  test()方法: test.html:  3.打开宝塔面板,放行9502......
  • 坐牢第五天加第六天 20240709
    作业1、提示并输入一个字符串,统计该字符串中字母、数字、空格以及其他字符的个数代码:​#include<stdio.h>#include<string.h>intmain(intargc,charconst*argv[]){chararr[100];inta,c,d,e=0;printf("请输入一个字符串:");gets(arr);f......