Linux局域网聊天室博客园,基于UDP套接字的局域网聊天室

该代码实现了一个基于UDP的简单聊天室服务端和客户端。服务端使用链表管理用户,接收到不同类型的请求(注册、删除、广播)后进行相应操作。客户端通过输入用户名并发送注册请求加入聊天室,然后可以接收和发送消息,当输入'quit'退出。
摘要由CSDN通过智能技术生成

#include #include #include #include #include #include #include

#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 \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 #include #include #include #include #include #include #include

#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 \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("");

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、付费专栏及课程。

余额充值