您当前的位置: 首页 >  udp

MangataTS

暂无认证

  • 6浏览

    0关注

    423博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

LinuxC语言のUDP简易聊天室 sokcet

MangataTS 发布时间:2021-11-01 17:19:00 ,浏览量:6

设计思路

考虑到只是一个简易版本的UDP聊天服务,所以很多不完善的地方

服务器

服务器我是开了一个父子进程,分别负责的

  • 接受客户端的消息&&发送某一个客户端的信息
  • 服务器的命令终端(只不过没有实现,只写了广播功能)

然后我封装了一个数据结构,每当客户端发一个包过来,这个包由三部分组成

  • 消息类型(login、cheat、end)
  • 发送者的姓名
  • 发送者的消息构成

然后我们分三种情况来解析这三种消息就行,具体实现就是一个简单的链表结构,详情可以看代码。

CODE
/*
 *
 * 缺点:
 * 1.以奇怪的方式下线的用户不能清理
 * 
 */


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define false 0
#define true 1

#define N 1024

struct MSG{//消息封装
    char type;
    char name[20];
    char text[N];
};

struct Node {//用户节点信息
    struct sockaddr_in addr;
    struct Node * next;
};

struct Node * init() {//用户节点初始化
    struct Node * p = (struct Node *)malloc(sizeof(struct Node));
    memset(p,0,sizeof(struct Node));
    p->next = NULL;
    return p;
}

const char *ip = "127.0.0.1";
const int port = 8000;
struct Node *head;

void login(int sockfd,struct MSG msg,struct sockaddr_in clientaddr) {//登陆消息
    struct Node *p = head;
    strcpy(msg.text,msg.name);
    msg.text[strlen(msg.text) - 1]  = '\0';
    strcat(msg.text," 已经上线欢迎来聊^_^~");
    //puts(msg.text);
    int cnt = 0;
    while(p->next) {//发给已经上线的用户
        if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->next->addr,sizeof(p->next->addr)) next;
        cnt++;
    }
    struct Node *k = (struct Node *)malloc(sizeof(struct Node));
    k->addr = clientaddr;
    k->next = NULL;
    p->next = k;
    printf("当前总用户数:%d \n上线用户的port: %u \n",cnt,ntohl(clientaddr.sin_port));
}

void chat(int sockfd,struct MSG msg,struct sockaddr_in clientaddr) {//聊天消息处理函数
    struct Node *p = head;   
    char str[N]= {0};
    //puts(msg.name);
    //puts(msg.text);
    sprintf(str,"%s : %s",msg.name,msg.text);
    strcpy(msg.text,str);
    puts(msg.text);//输出到服务器终端
    while(p->next) {
        if (memcmp(&clientaddr, &p->next->addr, sizeof(clientaddr)) != 0) {
            if (sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *) &p->next->addr, sizeof(p->next->addr)) next;
    }
}

void quit(int sockfd,struct MSG msg,struct sockaddr_in clientaddr) {//退出函数
    struct Node *p = head;
    struct Node *q = NULL;
    sprintf(msg.text,"%s用户已下线",msg.name);
    puts(msg.text);
    while(p->next) {//因为头号节点是服务器
        if(memcmp(&clientaddr,&p->next->addr,sizeof(clientaddr)) == 0) {
            q = p->next;
            p->next = q->next;
            free(q);
            q=NULL;//free后将指针赋为NULL
        }
        else {
            sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr*)&p->next->addr,sizeof(p->next->addr));
        }
        p = p->next;
    }
}

int socketfd;

void my_end(int sign_no) {//这个是注册一个ctr+c退出时候的一个信号处理
    close(socketfd);
    exit(1);
}

int main() {
    signal(SIGINT,my_end);
    head = init();
    struct sockaddr_in serveraddr,clientaddr;
    bzero(&serveraddr,sizeof(serveraddr));
    bzero(&clientaddr,sizeof(clientaddr));

    struct MSG msg;
    socklen_t addrlen = sizeof(struct sockaddr);
    char buf[N] = "";
    if((socketfd = socket(AF_INET, SOCK_DGRAM, 0))            
关注
打赏
1665836431
查看更多评论
0.0399s