基于UDP的简易聊天室(服务器端)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define N 64


#define TYPE_R   1    // register 
#define TYPE_B   2    // broadcast
#define TYPE_P   3    // private talk
#define TYPE_U   4 // unregister
#define TYPE_Q   5    // quit
#define TYPE_L   6    // user list


typedef struct sockaddr SA;


typedef struct 
{
int type;
char from[16];
char to[16];
char text[N];
}MESG;


typedef struct _node_
{
struct sockaddr_in peeraddr;
char name[16];
struct _node_ *next;


}linknode,*linklist;


linklist CreateLinklist()
{
linklist h;


h = (linklist)malloc(sizeof(linknode));
h->next = NULL;


return h;
}


AddUser(int sockfd,struct sockaddr_in peeraddr ,MESG buf ,linklist h)//添加成员
{
linklist p = (linklist)malloc(sizeof(linknode));
p->peeraddr = peeraddr;
strcpy(p->name,buf.from);
p->next = h->next;
h->next = p;

buf.type =TYPE_B;
sprintf(buf.text,"%s is online\n",buf.from);
strcpy(buf.from,"system");
h = h->next;
while(h)
{
sendto(sockfd,&buf,sizeof(buf),0,(SA *)&h->peeraddr,sizeof(peeraddr));
h = h->next;
}
return;

}






void Private(int sockfd,struct sockaddr_in peeraddr ,MESG buf ,linklist h)//私聊
{
h = h->next;
while(h)
{
if(strcmp(h->name,buf.to) == 0)
break;
h = h->next;
}
strcpy(buf.from,h->name);
sendto(sockfd,&buf,sizeof(buf),0,(SA *)&h->peeraddr,sizeof(peeraddr));

}




void Broadcast(int sockfd,struct sockaddr_in peeraddr,MESG buf,linklist h)//群聊,广播
{
h = h->next;
while(h)
{
if(strcmp(buf.from,h->name) == 0)
{
h = h->next;
continue;
}
sendto(sockfd,&buf,sizeof(buf),0,(SA *)&h->peeraddr,sizeof(peeraddr));
h = h->next;
}
return;
}




void DelUser(int sockfd,struct sockaddr_in peeraddr,MESG buf,linklist h)//删除成员
{
linklist p = (linklist)malloc(sizeof(linknode));
p = h;
h = h->next;
while(h)
{
if(strcmp(buf.from,h->name) == 0)
{
h = h->next;
continue;
}
sendto(sockfd,&buf,sizeof(buf),0,(SA *)&h->peeraddr,sizeof(peeraddr));
h = h->next;
}
linklist q = (linklist)malloc(sizeof(linknode));
q = p;
p = p->next;
while(p)
{
if(strcmp(buf.from,p->name) == 0)
{
q->next = p->next;
free(p);
break;
}
q = p;
p = p->next;
}
return;
}


void List(int sockfd,struct sockaddr_in peeraddr,MESG buf,linklist h)//显示所有在线成员
{
h = h->next;
while(h)
{
strcpy(buf.text,h->name);
sendto(sockfd,&buf,sizeof(buf),0,(SA *)&peeraddr,sizeof(peeraddr));
h = h->next;
}
}
int main(int argc,char *argv[])
{
pid_t pid;
int sockfd;
MESG buf;
struct sockaddr_in myaddr,peeraddr;
if (argc < 3)
{
printf("Usage : %s <my_ip> <my_port>\n", argv[0]);
exit(-1);
}
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("fail to socket");
exit(-1);
}


bzero(&myaddr, sizeof(myaddr));
myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(atoi(argv[2]));
myaddr.sin_addr.s_addr = inet_addr(argv[1]);


if (bind(sockfd, (SA *)&myaddr, sizeof(myaddr)) < 0)
{
perror("fail to bind");
exit(-1);
}


if((pid =fork()) < 0)
{
perror("fail to fork");
exit(-1);
}
else if(pid == 0)
{
linklist h = CreateLinklist();
while(1)
{
socklen_t peerlen = sizeof(peeraddr);
recvfrom(sockfd,&buf,sizeof(buf),0,(SA *)&peeraddr,&peerlen);
switch(buf.type)
{
case TYPE_R:
AddUser(sockfd,peeraddr ,buf,h);
break;
case TYPE_B:
Broadcast(sockfd,peeraddr,buf,h);
break;
case TYPE_P:
Private(sockfd,peeraddr,buf,h);
break;
case TYPE_U:
DelUser(sockfd,peeraddr,buf,h);
break;
case TYPE_L:
List(sockfd,peeraddr,buf,h);
break;
}
}
}
else
{
while(1)
{
printf("<system> ");
fgets(buf.text,N,stdin);
if(strncmp(buf.text,"quit",4) == 0)
{
printf("byebye!\n");
kill(0,SIGKILL);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值