聊天室功能:
1.其他用户上线通知。
2.其他用户下线通知。
3.获取在线列表。
4.用户之间点对点聊天。
实现思想:
1.服务器端主要是解析客户端发送过来的各种指令,并作出相应的处理和回应。
2.客户端采用select管理套接口IO和标准输入IO,当有事件发生,做出相应的处理。
3.采用链表存储每个客户端的网络信息,登录对应聊表插入(使用头插法),退出对应链表删除。点对点对应链表的遍历查找。
源代码:
服务器端:
#include "pub.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <poll.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <algorithm>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0);
//聊天室成员列表
USER_LIST client_list;
void chat_server(int server_fd);
void do_login(MESSAGE msg,int sock,struct sockaddr_in *clientaddr);
void do_logout(MESSAGE msg,int sock,struct sockaddr_in *clientaddr);
void do_online_user(int sock,struct sockaddr_in *clientaddr);
int main(void)
{
int sock;
struct sockaddr_in servaddr;
if ((sock = socket(AF_INET,SOCK_DGRAM,0)) < 0)
ERR_EXIT("socket");
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(9999);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
ERR_EXIT("bind");
chat_server(sock);
return 0;
}
void chat_server(int server_fd)
{
struct sockaddr_in clientaddr;
socklen_t clientlen;
int n;
MESSAGE msg;
while (1)
{
memset(&msg,0,sizeof(msg));
clientlen = sizeof(clientaddr);
n = recvfrom(server_fd,&msg,sizeof(msg),0,(struct sockaddr*)&clientaddr,&clientlen);
if (n < 0)
{
if (errno == EINTR)
continue;
ERR_EXIT("recvfrom");
}
int cmd = ntohl(msg.cmd);
switch (cmd)
{
case C2S_LOGIN:
do_login(msg,server_fd,&clientaddr);
break;
case C2S_LOGOUT:
do_logout(msg,server_fd,&clientaddr);
break;
case C2S_ONLINE_USER:
do_online_user(server_fd,&clientaddr);
break;
default:
break;
}
}
}
void do_login(MESSAGE msg,int sock,struct sockaddr_in *clientaddr)
{
USER_INFO user;
strcpy(user.username,msg.body);
user.ip = clientaddr->sin_addr.s_addr;
user.port = clientaddr->sin_port;
/*查找用户*/
USER_LIST::iterator it;
for (it=client_list.begin(); it!=client_list.end(); ++it)
{
if (strcmp(it->username,msg.body) == 0)
{
break;
}
}
if (it == client_list.end()) //没找到用户
{
printf("has a u