基于UDP的简单聊天室

聊天室功能:

        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
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值