linux下 UDP 实现聊天室

/*********************************客户端***************************************/

#include <stdio.h>

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


typedef struct sockaddr SA;


#define  N  64


#define  R  1
#define  U  2
#define  B  3
#define  E  4


typedef struct
{
int type;
char name[16];
char text[N];
} MSG;


int main(int argc, char *argv[])
{
int sockfd;
MSG buf;
pid_t pid;
struct sockaddr_in servaddr;


if (argc < 3)
{
printf("Usage : %s <ip> <port>\n", argv[0]);
return -1;
}


printf("pleast input your name : ");
fgets(buf.name, 16, stdin);
buf.name[strlen(buf.name)-1] = '\0';


// XXX int socket(int domain, int type, int protocol);
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("fail to socket");
exit(-1);
}


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]);

buf.type = R;
sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr, sizeof(servaddr));


if ((pid = fork()) < 0)
{
perror("fail to fork");
exit(-1);
}
else if (pid == 0)   //  receive message
{
while ( 1 )
{
recvfrom(sockfd, &buf, sizeof(buf), 0, NULL, NULL);
if (buf.type == E) break;
printf("\n *** [%s] %s", buf.name, buf.text);
}
printf("server is down, exit...\n");
kill(getppid(), SIGUSR1);
exit(0);
}
else   //  send message
{
usleep(100000);
buf.type = B;
while ( 1 )
{
printf("%s > ", buf.name);
fgets(buf.text, N, stdin);
if (strcmp(buf.text, "quit\n") == 0) break;
sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr, sizeof(servaddr));
usleep(100000);
}
buf.type = U;
sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr, sizeof(servaddr));
usleep(100000);
kill(pid, SIGUSR1);
exit(0);
}


return 0;

}

/********************************服务器**************************************/

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


typedef struct sockaddr SA;


#define  N  64


#define  R  1
#define  U  2
#define  B  3
#define  E  4


typedef struct
{
int type;
char name[16];
char text[N];
} MSG;


typedef struct _node_
{
struct sockaddr_in cliaddr;
struct _node_ *next;
} linknode, *linklist;


void AddUser(int sockfd, MSG buf, struct sockaddr_in peeraddr, linklist h)
{
linklist p;


p = (linklist)malloc(sizeof(linknode));
p->next = h->next;
h->next = p;
p->cliaddr = peeraddr;


sprintf(buf.text, "%s is online\n", buf.name);
strcpy(buf.name, "system");
p = p->next;
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));


}


void DelUser(int sockfd, MSG buf, struct sockaddr_in peeraddr, linklist h)
{
linklist p = h->next;


sprintf(buf.text, "%s is offline\n", buf.name);
strcpy(buf.name, "system");
while (p != NULL)
{
if (memcmp(&p->cliaddr, &peeraddr, sizeof(peeraddr)) == 0)
{
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));
}


void Broadcast(int sockfd, MSG buf, linklist h)
{
h = h->next;


while (h != NULL)
{
sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&h->cliaddr, sizeof(h->cliaddr));
h = h->next;
}
}


int main(int argc, char *argv[])
{
int sockfd;
MSG buf;
pid_t pid;
struct sockaddr_in servaddr, peeraddr;
socklen_t peerlen = sizeof(peeraddr);


if (argc < 3)
{
printf("Usage : %s <ip> <port>\n", argv[0]);
return -1;
}


// XXX int socket(int domain, int type, int protocol);
if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("fail to socket");
exit(-1);
}


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 (bind(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0)
{
perror("fail to bind");
exit(-1);
}


if ((pid = fork()) < 0)
{
perror("fail to fork");
exit(-1);
}
else if (pid == 0)   //  receive message
{
linklist h;
h = (linklist)malloc(sizeof(linknode));
h->next = NULL;


while ( 1 )
{
recvfrom(sockfd, &buf, sizeof(buf), 0, (SA *)&peeraddr, &peerlen);
switch ( buf.type )
{
case R :
AddUser(sockfd, buf, peeraddr, h);
break;
case U :
DelUser(sockfd, buf, peeraddr, h);
break;
case B :
case E :
Broadcast(sockfd, buf, h);
break;
}
if (buf.type == E) exit(0);
}
}
else   //  send message
{
buf.type = B;
strcpy(buf.name, "system");
while ( 1 )
{
printf("server > ");
fgets(buf.text, N, stdin);
if (strcmp(buf.text, "quit\n") == 0) break;
sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr, sizeof(servaddr));
usleep(100000);
}
buf.type = E;
sendto(sockfd, &buf, sizeof(buf), 0, (SA *)&servaddr, sizeof(servaddr));
usleep(100000);
exit(0);
}


return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值