项目:基于UDP的网络聊天室
项目需求:
1.如果有用户登录,其他用户可以收到这个人的登录信息
2.如果有人发送信息,其他用户可以收到这个人的群聊信息
3.如果有人下线,其他用户可以收到这个人的下线信息
4.服务器可以发送系统信息
服务器代码:
#include <myhead.h>
typedef struct group
{
char type;
char name[20];
char text[128];
}gp_t;
typedef struct Node
{
int PORT;
struct Node* next;
}*Linklist;
Linklist create_node()
{
Linklist s=(Linklist)malloc(sizeof(struct Node));
if(NULL == s)
return NULL;
s->PORT =0;
s->next =NULL;
return s;
}
Linklist insert_rear(Linklist head,int element)
{
Linklist s=create_node();
s->PORT=element;
if(NULL == head)
{
head = s;
return head;
}
Linklist p = head;
while(p->next != NULL)
{
p=p->next;
}
p->next = s;
return head;
}
int lenth(Linklist head)
{
if(head == NULL)
return 0;
int count=0;
Linklist p=head;
while(p!=NULL)
{
count++;
p=p->next;
}
free(p);
p=NULL;
return count;
}
int find_element(Linklist head,int element)
{
Linklist p=head;
for(int i=0;i<lenth(head);i++)
{
if(p->PORT == element)
return i;
p=p->next;
}
}
Linklist del_head(Linklist head)
{
if(head->next == NULL)
{
free(head);head=NULL;
return head;
}
Linklist del=head->next;
head->PORT=del->PORT;
head->next=del->next;
free(del);del=NULL;
return head;
}
Linklist del_rear(Linklist head)
{
if(head->next == NULL)
{
free(head);
head = NULL;
return head;
}
Linklist del=head;
while(del->next->next!=NULL)
{
del=del->next;
}
free(del->next);
del->next=NULL;
return head;
}
Linklist del_pos(Linklist head,int pos)
{
if(pos == lenth(head)-1)
{
head = del_rear(head);
return head;
}
else if(pos == 0)
{
head = del_head(head);
return head;
}
else
{
Linklist p=head;
for(int i=0;i<pos-1;i++)
{
p=p->next;
}
Linklist r=p->next;
p->next=r->next;
free(r);
r=NULL;
return head;
}
}
Linklist del(Linklist head,int element)
{
if(head ==NULL)
return head;
int pos = find_element(head,element);
head = del_pos(head,pos);
return head;
}
int main(int argc, const char *argv[])
{
if(argc != 3)
{
printf("请输入服务器IP和端口号!\n");
return -1;
}
int sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd == -1)
{
perror("socket error");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
sin.sin_addr.s_addr = inet_addr(argv[1]);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
struct sockaddr_in cin;
cin.sin_family = AF_INET;
socklen_t socklen = sizeof(cin);
Linklist Usr_PORT=NULL;
gp_t usr;
char buf[149] = "";
char rbuf[130] = "";
struct pollfd fds[2];
fds[0].fd = 0;
fds[0].events = POLLIN;
fds[1].fd = sfd;
fds[1].events = POLLIN;
int res = 0; //接收select的返回值
while(1)
{
res = poll(fds,2,-1);
if(res == -1)
{
perror("poll error");
return -1;
}
else if(res == 0)
{
printf("time out");
return -1;
}
bzero(buf,sizeof(buf));
if(fds[0].revents == POLLIN)
{
strcpy(buf,"system:");
fgets(buf+7,sizeof(buf)-7,stdin);
buf[strlen(buf)-1] = '\0';
Linklist p = Usr_PORT;
while(p!= NULL)
{
cin.sin_port = htons(p->PORT);
sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
p=p->next;
}
}
if(fds[1].revents == POLLIN)
{
recvfrom(sfd,&usr,sizeof(usr),0,(struct sockaddr*)&cin,&socklen);
if(usr.type == 'L')
{
Usr_PORT = insert_rear(Usr_PORT,ntohs(cin.sin_port));
printf("[%s:%d]已经上线\n",usr.name,ntohs(cin.sin_port));
sprintf(buf,"-----%s已经上线-----",usr.name);
printf("buf = %s\n",buf);
Linklist p = Usr_PORT;
while(p->next!= NULL)
{
cin.sin_port = htons(p->PORT);
sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
p=p->next;
}
}
else if(usr.type == 'C')
{
sprintf(buf,"%s:%s",usr.name,usr.text);
Linklist p = Usr_PORT;
int NONE=ntohs(cin.sin_port);
while(p!= NULL)
{
if(NONE!=p->PORT)
{
cin.sin_port = htons(p->PORT);
sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&(cin),sizeof(cin));
}
p=p->next;
}
}
else if(usr.type == 'Q')
{
sprintf(buf,"-----%s已经下线-----",usr.name);
printf("[%s:%d]已经离线\n",usr.name,ntohs(cin.sin_port));
Usr_PORT = del(Usr_PORT,ntohs(cin.sin_port));
Linklist p = Usr_PORT;
while(p!= NULL)
{
cin.sin_port = htons(p->PORT);
sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,sizeof(cin));
p=p->next;
}
}
}
}
close(sfd);
return 0;
}
客户端代码:
#include <myhead.h>
typedef struct
{
char type;
char name[20];
char text[128];
}gp_t;
int main(int argc, const char *argv[])
{
if(argc != 3)
{
printf("请输入服务器IP和端口号!\n");
return -1;
}
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd == -1)
{
perror("socket error");
return -1;
}
gp_t GP;
char name[20] = "";
printf("请输入用户名>>");
scanf("%s",GP.name);
getchar();
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[2]));
sin.sin_addr.s_addr = inet_addr(argv[1]);
char buf[130] = "";
char rbuf[128] = "";
bzero(buf,sizeof(buf));
GP.type = 'L';
sendto(cfd,&GP,sizeof(GP),0,(struct sockaddr*)&sin,sizeof(sin));
struct pollfd fds[2];
fds[0].fd = 0;
fds[0].events = POLLIN;
fds[1].fd = cfd;
fds[1].events = POLLIN;
int res = 0;
while(1)
{
res = poll(fds,2,-1);
if(res == -1)
{
perror("poll error");
return -1;
}
else if(res == 0)
{
printf("time out\n");
return -1;
}
bzero(buf,sizeof(buf));
bzero(rbuf,sizeof(rbuf));
if(fds[1].revents == POLLIN)
{
recvfrom(cfd,rbuf,sizeof(rbuf),0,NULL,NULL);
printf("%s\n",rbuf);
}
if(fds[0].revents == POLLIN)
{
fgets(GP.text,sizeof(GP.text),stdin);
GP.text[strlen(GP.text)-1]='\0';
if(strcmp(GP.text,"quit")==0)
{
GP.type = 'Q';
sendto(cfd,&GP,sizeof(GP),0,(struct sockaddr*)&sin,sizeof(sin));
goto A;
}
GP.type = 'C';
sendto(cfd,&GP,sizeof(GP),0,(struct sockaddr*)&sin,sizeof(sin));
}
}
A:
close(cfd);
return 0;
}