基于UDP套接字的局域网聊天室

需要实现功能如下:
1.服务器端功能如下:
广播通知客服端登录/退出
接受客服端发来的消息,广播给所有用户
广播系统消息
2.客服端功能如下:
接收服务器发来的消息并显示
发送消息给服务器端
 
实现代码如下:
1.服务器端代码:
 

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#define R 1
#define U 2
#define B 3
#define N 64
typedef struct
{
 int type;
 char name[16];
 char text[N];
} MESG;
typedef struct sockaddr SA;
typedef struct _node_
{
 struct sockaddr_in cliaddr;
 struct _node_ *next;
} linknode, *linklist;
linklist CreateEmptyLinklist()
{
 linklist h;
 h = (linklist)malloc(sizeof(linknode));
 h->next = NULL;
 return h;
}
void AddUser(int sockfd, linklist h, struct sockaddr_in peeraddr, MESG buf)
{
 linklist p;
 printf("AddUser()\n");
 p = (linklist)malloc(sizeof(linknode));
 p->cliaddr = peeraddr;
 p->next = h->next;
 h->next = p;
 p = p->next;
 sprintf(buf.text, "%s is online\n", buf.name);
 strcpy(buf.name, "system");
 while (p != NULL)
 {
  sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&p->cliaddr, sizeof(peeraddr));
  p = p->next;
 }
 strcpy(buf.text, "Welcome to Farsight Chat Room\n");
 sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&peeraddr, sizeof(peeraddr));
 return;
}
void DelUser(int sockfd, linklist h, struct sockaddr_in peeraddr, MESG buf)
{
 linklist p = h->next;
 printf("DelUser()\n");
 sprintf(buf.text, "%s is offline\n", buf.name);
 strcpy(buf.name, "system");
 while (p != NULL)
 {
  if ((p->cliaddr.sin_addr.s_addr == peeraddr.sin_addr.s_addr) &&
   (p->cliaddr.sin_port == peeraddr.sin_port))
  {
   h->next = p->next;
   free(p);
  }
  else
  {
   sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&p->cliaddr, sizeof(peeraddr));
   h = h->next;
  }
  p = h->next;
 }
 strcpy(buf.text, "See you next time\n");
 sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&peeraddr, sizeof(peeraddr));
 return;
}
void Broadcast(int sockfd, linklist h, MESG buf)
{
 h = h->next;
 while (h != NULL)
 {
  sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&h->cliaddr, sizeof(h->cliaddr));
  h = h->next;
 }
 return;
}
int main(int argc, char *argv[])
{
 int sockfd;
 MESG buf;
 struct sockaddr_in myaddr, peeraddr;
 socklen_t peerlen;
 linklist h;
 if (argc < 3)
 {
  printf("Usage : %s <ip> <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);
 }
 h = CreateEmptyLinklist();
 while ( 1 )
 {
  peerlen = sizeof(peeraddr);
  recvfrom(sockfd, &buf, sizeof(buf), 0, (SA *)&peeraddr, &peerlen);
  switch ( buf.type )
  {
  case R:
   AddUser(sockfd, h, peeraddr, buf);
   break;
  case U:
   DelUser(sockfd, h, peeraddr, buf);
   break;
  case B:
   Broadcast(sockfd, h, buf);
   break;
  }
 }
 return 0;
}
2.客服端代码如下:

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define R 1
#define U 2
#define B 3
#define N 64
typedef struct
{
 int type;
 char name[16];
 char text[N];
} MESG;
typedef struct sockaddr SA;
/*
typedef struct _node_
{
 struct sockaddr_in cliaddr;
 struct _node_ *next;
} linknode, *linklist;
*/
int main(int argc, char *argv[])
{
 int sockfd;
 MESG buf;
 struct sockaddr_in servaddr;
 if (argc < 3)
 {
  printf("Usage : %s <serv_ip> <serv_port>\n", argv[0]);
  exit(-1);
 }
 printf("please input your login name : ");
 fgets(buf.name, 16, stdin);
 buf.name[strlen(buf.name)-1] = '\0';
 bzero(&servaddr, sizeof(servaddr));
 servaddr.sin_family = PF_INET;
 servaddr.sin_port = htons(atoi(argv[2]));
 servaddr.sin_addr.s_addr = inet_addr(argv[1]);
 if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
 {
  perror("fail to socket");
  exit(-1);
 }
 // XXX: register
 buf.type = R;
 sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr, sizeof(servaddr));
 pid_t pid;
 if ((pid = fork()) == 0)  // child process
 {
  while ( 1 )
  {
   recvfrom(sockfd, &buf, sizeof(buf), 0, NULL, NULL);
   printf("[%s] %s", buf.name, buf.text);
  }
 }
 else   // parent process
 {
  buf.type = B;
  while ( 1 )
  {
   printf("<client> ");
   fgets(buf.text, N, stdin);
   if (strncmp(buf.text, "quit", 4) == 0)
   {
    buf.type = U;
    sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr,sizeof(servaddr));
    usleep(100000);
    kill(pid, SIGKILL);
    exit(0);
   }
   sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr,sizeof(servaddr));
  }
 } 
 return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值