#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;
}