UDP聊天室

#include<stdio.h>
#include <sys/types.h>      
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include<unistd.h>
#include<arpa/inet.h>
#include<string.h>
#include<stdlib.h>
#include <sys/wait.h>
#include<dirent.h>
#include<sys/stat.h>
#include<signal.h>
#include <pthread.h>
//服务器端
struct sockaddr_in saddr,caddr;
chos type_t
{
    Login,
    Chat,
    Quit,
};
typedef struct MSG
{
    char type;//选哪个功能
    char name[20];
    char text[128];
}msg_t;

typedef struct NODE
{
    struct sockaddr_in caddr;
    struct NODE *next;
}node_t;

node_t *create_node(void)
{
    node_t *p=(node_t *)malloc(sizeof(node_t));
    p->next=NULL;
    return p;

}
void login(int ,msg_t ,node_t *,struct sockaddr_in);//登录的函数
void chat(int ,msg_t ,node_t *,struct sockaddr_in);//群聊的函数
void quit(int ,msg_t ,node_t *,struct sockaddr_in);//退出函数
int main(int argc, char const *argv[])
{
    if(argc !=3)
    {
        printf("Usage:./a.out <port>\n");
        return -1;
    }
    //创建UDP套接字
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        perror("socket err");
        return -1;
    }
   
    s.sin_family=AF_INET;
    s.sin_port=htons(atoi(argv[2]));
    s.sin_addr.s_addr=inet_addr(argv[1]);
    socklen_t len = sizeof(caddr);

   if( bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr)== -1)
  {
    perror("bind error");
    return -1;
   }
    msg_t msg;
    node_t *p=create_node();
    while(1)
   {
        if(recvfrom(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&caddr,&len)<0)
        {
            perror("recvfrom error");
            return -1;
        }
            if(msg.type==Login)
        {
            strcpy(msg.text,"上线");
                printf("ip:%spord:%name:%s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),msg.name);
            printf("状态:%s\n",msg.text);
            do_login(sockfd,msg,p,caddr);
        }
            else if(msg.type==Chat)
        {
            do_chat(sockfd,msg,p,caddr);    
        }
        else if(msg.type==Quit)
        {
            strcpy(msg.text,"下线");
                printf("ip:%spord:%dname:%s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),msg.name);
            printf("状态:%s\n",msg.text);
            do_quit(sockfd,msg,p,caddr);        
        }
    }
    close(sockfd);
    return 0;
}
//登录
void login(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
{
    
    sprintf(msg.text," %s上线",msg.name);
    while(p->next!= NULL)
    {
        p= p->next;
        sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));
        //printf("%s\n",msg.text);
    }
    node_t *new=(node_t *)malloc(sizeof(node_t));
    new->caddr=caddr;
    new->next=NULL;
    p->next=new;
    return;
}
//聊天
void chat(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
{
    while(p->next != NULL)
    {
        p=p->next;
        
        if(memcmp(&(p->caddr),&caddr,sizeof(caddr)) != 0)
        {
           sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));
        }
    }
    return;
}
//退出函数
void quit(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
{
    sprintf(msg.text,"%s 下线",msg.name);
    while(p->next != NULL)
    {
        if((memcmp(&(p->next->caddr),&caddr,sizeof(caddr)))==0)
        { 
            node_t *dele=NULL;
            dele = p->next;
            p->next=dele->next;
            free(del);
            dele=NULL;
        }
      else
      {
          p=p->next;
          sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));
      }  
    }
    return;
}
#include<stdio.h>
#include <sys/types.h>      
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include<unistd.h>
#include<arpa/inet.h>
#include<string.h>
#include<stdlib.h>
#include <sys/wait.h>
#include<dirent.h>
#include<sys/stat.h>
#include<signal.h>
#include <pthread.h>
//客户端
chos type_t
{
    Login,
    Chat,
    Quit,
};
typedef struct 
{
    char type;
    char name[32];//
    char text[128];//
}msg_t;

int main(int argc, char const *argv[])
{
     if(argc !=3)
    {
        printf("Usage ./a.out [ip:port]\n");
        return -1;
    }
   
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        perror("socket err");
        exit(-1);
    }
    struct sockaddr_in saddr;
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(atoi(argv[2]));
    saddr.sin_addr.s_addr=inet_addr(argv[1]);
    socklen_t len = sizeof(saddr);
    msg_t msg;
    //先执行登录操作 
    printf("请登录:\n");
    msg.type=Login;
    printf("请输入用户名:");
    fgets(msg.name,32,stdin);
    if(msg.name[strlen(msg.name)-1]=='\n')
       msg.name[strlen(msg.name)-1]='\0';
    //发送登录消息
    if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&saddr,len)<0)
       {
         perror("sendto err");
         exit(-1);
       }
    pid_t pid=fork();
     if(pid<0)
    {
        perror("fork err");
        exit(-1);
    }
    else if(pid==0)
    {
        while(1)
        {
            if(recvfrom(sockfd,&msg,sizeof(msg),0,NULL,NULL)<0)
            {
                perror("recvfrom err");
                return -1;
            }
            printf("[%s]:%s\n",msg.name,msg.text);
        } 
    }    
    else 
    {
        while(1)
        {
            fgets(msg.text,sizeof(msg.text),stdin);
            if(msg.text[strlen(msg.text)-1]=='\n')
            {
               msg.text[strlen(msg.text)-1]='\0';
            }
            if(strcmp(msg.text,"quit")==0)
            {
                msg.type=Quit; 
                sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&saddr,len);
                return -1;
            }else
        {
            msg.type=Chat;
        }
        //发送消息
        sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&saddr,len);
        }
    }
    close(sockfd);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值