⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chatserver.cpp

📁 一个控制台console的聊天程序
💻 CPP
字号:

#include <winsock2.h>
#include <iostream.h>
#include <queue>
#include <list>
#include "ChatStruct.h"

#pragma comment(lib, "wsock32.lib")

HANDLE thread_commandHandle;			  	 //定义接收线程句柄
std::queue <MsgPair> msgQueue;				 //接收队列
std::list <UserOnline> userOnlineList;		 //在线用户队列
SOCKET sock;							     //socket

//服务器命令线程
void serverCommandThread();
//添加用户到列表
void addToOnlineQueue(sockaddr_in from,char *name);
//显示所有在线用户
void showOnlineQueue();
//用户退出聊天室
void logoutRoom(sockaddr_in &from);
//接收到聊天消息的处理函数
void recvMessage(sockaddr_in &from,GramHead* pHead,char *buf);
//发送消息
void sendMsg(char *data,char command);
//找出在线用户列表存放到pList中
void viewList(char *pList);
//将数据发送到指定地址
void sendListMsg(char *data,char command,sockaddr_in &from);


void main()
{	
	//1.启动SOCKET库,版本为2.0
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;	
	wVersionRequested = MAKEWORD( 2, 0 );	
	err = WSAStartup(wVersionRequested, &wsaData );
	if ( err != 0 ) 
	{
		cout<<"Socket2.0初始化失败,Exit!";
		return;
	}	
	if (LOBYTE(wsaData.wVersion)!= 2 ||	HIBYTE( wsaData.wVersion ) != 0 ) 
	{
		WSACleanup( );
		return; 
	}
	
	//2.创建socket,
	sock = socket(
		AF_INET,           //internetwork: UDP, TCP, etc
		SOCK_DGRAM,        //SOCK_DGRAM说明是UDP类型
		0                  //protocol
		);
	
	if (sock == INVALID_SOCKET ) {
		cout<<"Socket 创建失败,Exit!";
		return;
	}
	
	//3.绑定
	sockaddr_in myaddr; //sockaddr_in相当于sockaddr结构
	memset(&myaddr,0,sizeof(myaddr));
	myaddr.sin_family=AF_INET;
	myaddr.sin_addr.s_addr = ADDR_ANY;
	myaddr.sin_port=htons(5656);	
	bind(sock,(sockaddr*)&myaddr,sizeof(myaddr));
	
	cout<<"服务器开启成功!"<<endl;
	DWORD session_thread_id = 1;
	thread_commandHandle=CreateThread(0,
		0,
		(LPTHREAD_START_ROUTINE)serverCommandThread,
		0,
		0,
		&session_thread_id);

	//接收到的SOCK地址
	sockaddr_in from;
	memset(&from,0,sizeof(from));
	
	GramHead head,backHead;
	int fromlength = sizeof(SOCKADDR),nnlen;
	nnlen=fromlength;
	char *buf=new char[1024];
	memset(buf,0,1024);
	long number=0;
	while(1)
	{
		number++;
		// 这里必须指定1024即分配的空间大小。如果使用str(buf)则无法计算,因为还未初始化
		recvfrom(sock,buf,1024,0,(struct sockaddr FAR *)&from,(int FAR *)&fromlength);
		memcpy(&head,buf,sizeof(GramHead));
		switch(head.COMMAND)
		{
		case C_LOGIN:									//登陆成功
			backHead.COMMAND=S_LOGIN;
			memcpy(buf,&backHead,sizeof(GramHead));
			if( sendto(sock,buf,strlen(buf),0,(sockaddr*)&from,nnlen)
				== SOCKET_ERROR )
			cout<<WSAGetLastError()<<endl;
			cout<<"用户"<<(unsigned char*)head.USERNO<<"登陆到聊天室!"<<endl;
			addToOnlineQueue(from,head.USERNO);			//添加加用户到在线列表
			cout<<"聊天室当前人数为:"<<userOnlineList.size()<<endl;
//			showOnlineQueue();							//显示用户
			break;
		case C_LOGOUT:									//用户退出聊天室
			logoutRoom(from);
			break;
		case C_MESSAGE:									//用户聊天信息
			char data[1024-sizeof(GramHead)];
			memcpy(data,buf+sizeof(GramHead),1024-sizeof(GramHead));
			recvMessage(from,&head,data);
			break;
		case C_USERLIST:
			char plist[1024-sizeof(GramHead)];
			memcpy(plist,buf+sizeof(GramHead),1024-sizeof(GramHead));
			viewList(plist);
			sendListMsg(plist,S_USERLIST,from);
			break;
		}
		Sleep(500);
		memset(buf,0,sizeof(buf));

	}
	delete buf;	
	
	if (!closesocket(sock)) 
	{
		WSAGetLastError();
		return;
	}
	if (!WSACleanup()) 
	{
		WSAGetLastError();
		return;
	}
}


void addToOnlineQueue(sockaddr_in from,char *name)
{
	sendMsg(name,S_USERLOGIN);
	UserOnline online;
	online.clientAddr=from;
	strcpy(online.userName,name);
	userOnlineList.push_back(online);
}

void showOnlineQueue()
{
	int size=userOnlineList.size();
	if (size==0)
	{
		cout<<"当前没有用户在线...."<<endl;
		return;
	}
	else
	{
		cout<<"---------------------------------\n";
		cout<<"当前在线人数为:"<<size<<endl;
	}
	std::list<UserOnline>::iterator theIterator;
    for( theIterator = userOnlineList.begin(); theIterator != userOnlineList.end(); theIterator++ )
		cout<<"IP地址:"<<inet_ntoa(theIterator->clientAddr.sin_addr)
		<<"  端口号:"<<theIterator->clientAddr.sin_port<<" 用户名:"
		<<theIterator->userName<<endl;
	cout<<"---------------------------------\n";
}

void logoutRoom(sockaddr_in &from)
{
	char msg[1024-sizeof(GramHead)];
	std::list<UserOnline>::iterator theIterator;
    for( theIterator = userOnlineList.begin(); theIterator != userOnlineList.end(); theIterator++ )
	{
		if (inet_ntoa(theIterator->clientAddr.sin_addr)==inet_ntoa(from.sin_addr)
			&&theIterator->clientAddr.sin_port==from.sin_port)
		{
			memcpy(msg,theIterator->userName,sizeof(theIterator->userName));
			cout<<msg<<"离开了聊天室......"<<endl;
			userOnlineList.erase(theIterator);
			sendMsg(msg,S_LOGOUT);
			break;
		}
	}
	cout<<"当前在线人数为:"<<userOnlineList.size()<<endl;
}


void recvMessage(sockaddr_in &from,GramHead* pHead,char *buf)
{
	
	unsigned char dataBuf[1024];
	GramHead head;
	memcpy(head.USERNO,pHead->USERNO,sizeof(pHead->USERNO));
	head.COMMAND=C_RECVMESSAGE;
	memcpy(dataBuf,&head,sizeof(GramHead));
	memcpy(dataBuf+sizeof(GramHead),buf,1024-sizeof(GramHead));
	
	std::list<UserOnline>::iterator theIterator;
	for( theIterator = userOnlineList.begin(); theIterator != userOnlineList.end(); theIterator++ )
	{	
		if(sendto(sock,(const char *)dataBuf,1024,0,(sockaddr*)&theIterator->clientAddr,sizeof(SOCKADDR))
			== SOCKET_ERROR )
			cout<<WSAGetLastError()<<endl;
	}
}


void sendMsg(char *data,char command)
{
	char buf[1024];
	memset(buf,0,1024);
	GramHead head;
	head.COMMAND=command;

	memcpy(buf,&head,sizeof(GramHead));
	memcpy(buf+sizeof(GramHead),data,strlen(data));
	
	std::list<UserOnline>::iterator theIterator;
	for( theIterator = userOnlineList.begin(); theIterator != userOnlineList.end(); theIterator++ )
	{	
		if(sendto(sock,buf,1024,0,(sockaddr*)&theIterator->clientAddr,sizeof(SOCKADDR))
			== SOCKET_ERROR )
		cout<<WSAGetLastError()<<endl;
	}

}

void sendListMsg(char *data,char command,sockaddr_in &from)
{
	char buf[1024];
	memset(buf,0,1024);
	GramHead head;
	head.COMMAND=command;
	
	memcpy(buf,&head,sizeof(GramHead));
	memcpy(buf+sizeof(GramHead),data,strlen(data));
	if(sendto(sock,buf,1024,0,(sockaddr*)&from,sizeof(SOCKADDR))
		== SOCKET_ERROR )
			cout<<WSAGetLastError()<<endl;
}

//用户输入命令,完成操作
void serverCommandThread()
{
	char ch[1024-sizeof(GramHead)];
	while (1)
	{
		Sleep(1000);
		memset(ch,0,1024);
		cin>>ch;
		if (!strcmp(ch,"list"))
		{
			showOnlineQueue();
		}
		else if(!strcmp(ch,"help"))
		{
			cout<<"---------------------------------\n";
			cout<<"[list] 命令查看在线用户列表"<<endl;
			cout<<"[send] 命令发送信息"<<endl;
			cout<<"---------------------------------\n";
		}
		else if(ch[0]=='s'&&ch[1]=='e'&&ch[2]=='n'&&ch[3]=='d')
		{
			sendMsg(ch+4,S_MESSAGE);
		}
		
	}
}

void viewList(char *pList)
{
	memset(pList,0,1024);
	int start=0,length=0;
	std::list<UserOnline>::iterator theIterator;
    for( theIterator = userOnlineList.begin(); theIterator != userOnlineList.end(); theIterator++ )
	{
		length=strlen(theIterator->userName);
		memcpy(pList+start,theIterator->userName,length);
		pList[start+length]='\n';
		start+=length+1;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -