udp聊天室 带有注册功能

fs:(运行在服务器上的)

main.cpp

#include<WinSock2.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma comment(lib,"ws2_32.lib")
#include"init.h"
#include"deal.h"

UserData *userdata[MaxUser];
int      userdatap=-1;

int main()
{

	InitData(userdata,MaxUser,userdatap);
	int iPort=DEFAULT_PORT;
	WSADATA wsaData;
	SOCKET sSocket;

	int iLen;

	int iSend;

	int iRecv;

	char send_buf[1000];

	char recv_buf[BUFFER_LENGTH];

	struct sockaddr_in ser,cli;

	char response[BUFFER_LENGTH];

	printf("----------------------\n");
	printf("Server Waiting\n");
	printf("----------------------\n");


	if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
	{printf("Failed to load Winsock.\n");return 0;}

	sSocket=socket(AF_INET,SOCK_DGRAM,0);
	if(sSocket==INVALID_SOCKET){printf("socket()Faild:%d\n",WSAGetLastError());return 0;}

	ser.sin_family=AF_INET;
	ser.sin_port=htons(iPort);
	ser.sin_addr.s_addr=htonl(INADDR_ANY);

	if(bind(sSocket,(LPSOCKADDR)&ser,sizeof(ser))==SOCKET_ERROR)
	{printf("bind()Faild:%d\n",WSAGetLastError());return 0;}

	iLen=sizeof(cli);

	memset(recv_buf,0,sizeof(recv_buf));

	while(1)
	{
		//接收数据包 确定cli  表示 cli存有客户端发来的 ip和port 
		iRecv=recvfrom(sSocket,recv_buf,BUFFER_LENGTH,0,(SOCKADDR*)&cli,&iLen);
		if(iRecv==SOCKET_ERROR)
		{printf("recvfrom()Faild:%d\n",WSAGetLastError());return 0;}
		else if(iRecv==0) break;
		else 
		{// 接收到了正确数据
			//printf("Accepted client IP:[%s],port:[%d]\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));  
			//printf("recv:%s\n",recv_buf);

			memset(response,'\0',sizeof(response));
			deal(recv_buf,userdata,userdatap,response,inet_ntoa(cli.sin_addr));

			//返回的控制信息写在response里
			//控制信息的种类有00 01 10 11 12 20 21 30 31
			//00注册成功 01  注册失败 10登陆成功 11.12表示登陆失败  20表示一次成功会话 21表示错误会话 30表示成功推出  31表示错误推出
			//只有 20成功会话需要广播  21.31不予处理 其他会话只需把原信息发回给客户端即可
			int i;
			if(response[0]=='2' && response[1]=='0')
			{//处理20
				for(i=0;i<=userdatap;i++)
				{
					if(userdata[i]->Log==0)continue;

					cli.sin_addr.s_addr=inet_addr(userdata[i]->Ip);
					cli.sin_port=htons(DEFAULT_PORTSEND);

					MySendMessage(sSocket,response,sizeof(response),(SOCKADDR*)&cli,sizeof(cli));

				}
			}
			else
			{
				//printf("fa:%s\n",inet_ntoa(cli.sin_addr));
					cli.sin_port=htons(DEFAULT_PORTSEND);
					MySendMessage(sSocket,response,sizeof(response),(SOCKADDR*)&cli,sizeof(cli));
			
			
			}
		}
	}
	closesocket(sSocket);
	WSACleanup();
	
	return 0;
}
init.h

#include<stdlib.h>
#include<string.h>

//for main.cpp(1.cpp)
#define DEFAULT_PORT 5051//FOR RECV
#define DEFAULT_PORTSEND 5052//FOR SEND
#define BUFFER_LENGTH 1000

const bool Debug=0;
#define MaxUser 1000
//--------------------------------------------------------------------------------//
//当程序遇到异常而结束时会示出错误而退出
//--------------------------------------------------------------------------------//
//成员结构信息

#define UserNameLen 20
#define PasswordLen 20
typedef struct
{
	char UserName[20];
	char Password[20];
	bool Log;//是否登陆
	char Ip[20];
}
UserData;




//--------------------------------------------------------------------------------//
#define thefile "config.txt"
//初始化用户数据导入
bool InitData(UserData **s,int num,int &p)//成功返回true  发生错误返回false
{
	//-----------------------------------------//
	//读取文件信息并返回
	FILE *fp;
	char UserBuf[UserNameLen];
	char PassBuf[PasswordLen];

	fp=fopen(thefile,"r");
	if(!fp)
	{
		if(Debug)	printf("config文件不存在\n");
	}
	else
	{
		if(Debug)	printf("find config.txt\n");
		while(!feof(fp))
		{
			//fgets(buf,sizeof(buf),fp);
			fscanf(fp,"%s",UserBuf);
			fscanf(fp,"%s",PassBuf);

			if(Debug)	printf("[+]User:%s Password:%s\n",UserBuf,PassBuf);
			//add
			p++;
			s[p]=(UserData *)malloc(sizeof(UserData));
			if(!s[p]){printf("[+]ERROR:malloc failed!\n");return false;}
			strcpy(s[p]->UserName,UserBuf);
			strcpy(s[p]->Password,PassBuf);
			s[p]->Log=0;
			memset(s[p]->Ip,'\0',sizeof(s[p]->Ip));
		}
		fclose(fp);


	}


	

	return true;
}




bool SaveData(UserData **userdata,int userdatap)
{
	FILE *fp;
	///建立配置文件
	fp=fopen(thefile,"w");
	if(!fp){printf("[+]ERROR:无法创建config文件!");return false;};

	int i;
	for(i=0;i<=userdatap;i++)
	{
		fprintf(fp,"%s %s",userdata[i]->UserName,userdata[i]->Password);
		if(i!=userdatap)fprintf(fp,"\n");
	
	}
	fclose(fp);
}










deal.h

int findUser(UserData **data,int num,char *name)
{
	int i;
	for(i=0;i<=num;i++)
	{
		if(strcmp(name,data[i]->UserName)==0) return i;
	}
	return -1;


}



void deal(char *str,UserData **data,int &num,char *response,char *ip)
{
	char User[UserNameLen];
	char Pass[PasswordLen];
	//第一位字符是功能号 
	// 0 注册
	// 1 登陆
	// 2 会话
	// 3 退出
	int i,t;
	if(str[0]=='0')
	{
		//注册的消息格式为   0+name+@+password
		for(i=1;i<strlen(str);i++)
			if(str[i]=='@')break;
		str[i]='\0';

		strcpy(User,str+1);
		strcpy(Pass,str+i+1);

		t=findUser(data,num,User);
		if(t==-1)
		{//该用户名不存在,可以注册
			num++;
			data[num]=(UserData *)malloc(sizeof(UserData));
			if(data[num]==NULL){printf("[+]ERROR:malloc failed\n");exit(1);}
			strcpy(data[num]->UserName,User);
			strcpy(data[num]->Password,Pass);
			data[num]->Log=0;
			memset(data[num]->Ip,'\0',sizeof(data[num]->Ip));
			printf("%s 用户注册成功\n",User);

			//--------------------------------------------------注册完成
			//返回成功信息
			strcpy(response,"00");//第一位是功能号  第二位是状态号   0表示成功  1表示失败
			SaveData(data,num);
		}
		else
		{//fail
			printf("%s 用户注册失败\n",User);
			//-----------------------------------------------注册失败
			strcpy(response,"01");
		}

		;

	}
	else if(str[0]=='1')
	{

		//登陆的消息格式为   1+name+@+password
		for(i=1;i<strlen(str);i++)
			if(str[i]=='@')break;
		str[i]='\0';
		//printf("i=%d\n",i);
		strcpy(User,str+1);
		strcpy(Pass,str+i+1);

		t=findUser(data,num,User);
		if(t!=-1)
		{//找到该用户
			//printf("Pass=%s",Pass);
			//printf("Pawd=%s",data[t]->Password);
			if(strcmp(Pass,data[t]->Password)==0)
			{//密码验证成功
				printf("%s 登陆成功\n",User);

				data[t]->Log=1;
				strcpy(data[t]->Ip,ip);

				strcpy(response,"10");
			}
			else
			{
				printf("%s 登陆密码错误\n",User);
				strcpy(response,"11");
			}
		}
		else
		{
			printf("%s 用户不存在,登陆失败\n",User);
			strcpy(response,"12");
		}
		;
	}
	else if(str[0]=='2')
	{
		//会话的消息格式为  2+'name'+'@'+'(message)'
		for(i=1;i<strlen(str);i++)
			if(str[i]=='@')break;
		str[i]='\0';

		strcpy(User,str+1);
		t=findUser(data,num,User);

		if(t!=-1 && strcmp(data[t]->UserName,User)==0 && strcmp(data[t]->Ip,ip)==0)
		{
			//表示确实是正确用户发来的会话
			strcpy(response,"20");
			strcat(response,User);
			strcat(response,":");
			strcat(response,str+i+1);
			printf("%s:%s\n",User,str+i+1);
		}
		else
		{
			strcpy(response,"21");
			printf("非正确用户发来会话,不予处理!\n");
		}
	}
	else if(str[0]=='3')
	{

		//会话的消息格式为  3+'name'+'@'+'(message)'
		for(i=1;i<strlen(str);i++)
			if(str[i]=='@')break;
		str[i]='\0';

		strcpy(User,str+1);
		t=findUser(data,num,User);

		if(t!=-1 && strcmp(data[t]->UserName,User)==0 && strcmp(data[t]->Ip,ip)==0)
		{
			//表示确实是正确用户发来的会话
			strcpy(response,"30");
			data[t]->Log=0;
			memset(data[t]->Ip,'\0',sizeof(data[t]->Ip));
			printf("%s 退出\n",data[t]->UserName);
		}
		else
		{
			strcpy(response,"31");
			printf("非正确用户发来会话,不予处理!");
		}


	}



}






void MySendMessage(int sSocket,char *response,int responseLen,SOCKADDR* cli,int cliLen)
{
	int iSend;


	iSend=sendto(sSocket,response,responseLen,0,(SOCKADDR*)cli,cliLen);
	if(iSend==SOCKET_ERROR)
	{
		printf("sendto()Failed.:%d\n",WSAGetLastError());
	}
	else if(iSend==0) ;
	else
	{
		//printf("sendto() succeeded !\n");
		printf("----------------------\n");
	}



}

config.txt

admin admin
1 1
3 3
1 1234
5 644ad
0 0
6 6

接下来的两个文件运行在客户端上的

fcserver

main.cpp

#include<WinSock2.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma comment(lib,"ws2_32.lib")

#define DEFAULT_PORT 5052//FOR RECV
#define BUFFER_LENGTH 1000


void main()
{
	int iPort=DEFAULT_PORT;
	WSADATA wsaData;
	SOCKET sSocket;

	int iLen;

	int iSend;

	int iRecv;

	char send_buf[1000];

	char recv_buf[BUFFER_LENGTH];

	struct sockaddr_in ser,cli;

	printf("----------------------\n");
	printf("cServer Waiting\n");
	printf("----------------------\n");


	if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
	{printf("Failed to load Winsock.\n");return;}

	sSocket=socket(AF_INET,SOCK_DGRAM,0);
	if(sSocket==INVALID_SOCKET){printf("socket()Faild:%d\n",WSAGetLastError());return;}

	ser.sin_family=AF_INET;
	ser.sin_port=htons(iPort);
	ser.sin_addr.s_addr=htonl(INADDR_ANY);

	if(bind(sSocket,(LPSOCKADDR)&ser,sizeof(ser))==SOCKET_ERROR)
	{printf("bind()Faild:%d\n",WSAGetLastError());return;}

	iLen=sizeof(cli);

	memset(recv_buf,0,sizeof(recv_buf));

	while(1)
	{
		//接收数据包 确定cli  表示 cli存有客户端发来的 ip和port 
		iRecv=recvfrom(sSocket,recv_buf,BUFFER_LENGTH,0,(SOCKADDR*)&cli,&iLen);
		if(iRecv==SOCKET_ERROR)
		{printf("recvfrom()Faild:%d\n",WSAGetLastError());return;}
		else if(iRecv==0) break;
		else 
		{// 接收到了正确数据
			//printf("[+]%s\n",recv_buf);
			//控制信息的种类有00 01 10 11 12 20 21 30 31
			//00注册成功 01  注册失败 10登陆成功 11.12表示登陆失败  20表示一次成功会话 21表示错误会话 30表示成功推出  31表示错误推出
			
			switch(recv_buf[0])
			{
			case '0':
				if(recv_buf[1]=='0')printf("注册成功\n");
				else printf("注册失败\n");
				break;

			case '1':
				if(recv_buf[1]=='0')printf("登陆成功\n");
				else printf("登陆失败\n");
				break;

			case '2':
				printf("%s\n",recv_buf+2);
				break;			
			}			
		}
	}
	closesocket(sSocket);
	WSACleanup();
}

fcclient

main.cpp

#include<WinSock2.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma comment(lib,"ws2_32.lib")

#define DEFAULT_PORT 5051//FOR SEND
#define BUFFER_LENGTH 1024

void MySendMessage(SOCKET sSocket,char *response,int responseLen, struct sockaddr* cli,int cliLen);

void main(int argc,char *argv[])
{
	WSADATA wsaData;
	SOCKET sClient;
	int iPort=DEFAULT_PORT;

	int iLen;

	int iSend;
	int iRecv;

	char send_buf[1000];

	char recv_buf[BUFFER_LENGTH];

	struct sockaddr_in ser;

	if(argc<2){printf("usage:client [server IP address]\n");return;}

	memset(recv_buf,0,sizeof(recv_buf));
	if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
	{
		printf("Failed to load winsock.\n");
		return ;
	}

	//建立服务器信息 发送到目标机器  
	ser.sin_family=AF_INET;
	ser.sin_port=htons(iPort);
	ser.sin_addr.s_addr=inet_addr(argv[1]);

	sClient=socket(AF_INET,SOCK_DGRAM,0);
	if(sClient==INVALID_SOCKET)
	{printf("socket()Failed:%d\n",WSAGetLastError());return;}

	iLen=sizeof(ser);

	char user[20],password[20];
	char str[100];
	bool hasLogin=false;
	while(!hasLogin)
	{
		printf("--------------------------------\n");
		printf("0.注册\n");
		printf("1.登陆\n");
		printf("2.退出\n");
		printf("请输入相应的数字:\n>");
		scanf("%s",&str);
		switch(str[0])
		{
		case '0':
			printf("用户名:");
			scanf("%s",user);
			printf("密  码:");
			scanf("%s",password);

			strcpy(send_buf,"0");
			strcat(send_buf,user);
			strcat(send_buf,"@");
			strcat(send_buf,password);

			MySendMessage(sClient,send_buf,sizeof(send_buf),(struct sockaddr*)&ser,iLen);

			break;
		case '1':
			hasLogin=1;

			printf("用户名:");
			scanf("%s",user);
			printf("密  码:");
			scanf("%s",password);

			strcpy(send_buf,"1");
			strcat(send_buf,user);
			strcat(send_buf,"@");
			strcat(send_buf,password);

			MySendMessage(sClient,send_buf,sizeof(send_buf),(struct sockaddr*)&ser,iLen);
			printf("输入exit退出。\n");
			printf("--------------------------------\n");
			while(1)
			{
				printf(">");
				scanf("%s",&str);

				if(strcmp(str,"exit")!=0)
				{
					strcpy(send_buf,"2");
					strcat(send_buf,user);
					strcat(send_buf,"@");
					strcat(send_buf,str);


					MySendMessage(sClient,send_buf,sizeof(send_buf),(struct sockaddr*)&ser,iLen);
				}
				else
				{
					strcpy(send_buf,"3");
					strcat(send_buf,user);
					strcat(send_buf,"@");
					MySendMessage(sClient,send_buf,sizeof(send_buf),(struct sockaddr*)&ser,iLen);
					exit(0);
				}

			}



			break;


		case '2':

			exit(0);

			break;

		default:
			printf("--------------------------------\n");
			printf("请输入正确信息");

		}


	}



	closesocket(sClient);
	WSACleanup();
}





void MySendMessage(SOCKET sSocket,char *response,int responseLen, struct sockaddr* cli,int cliLen)
{
	int iSend;


	//int sendto ( socket s , const void * msg, int len, unsigned int flags, const struct sockaddr * to , int tolen ) ;
	iSend=sendto(sSocket,response,responseLen,0,(SOCKADDR*)cli,cliLen);
	//	iSend=sendto(sClient,send_buf,sizeof(send_buf),0,(struct sockaddr*)&ser,iLen);
	if(iSend==SOCKET_ERROR)
	{
		printf("sendto()Failed.:%d\n",WSAGetLastError());
	}
	else if(iSend==0) ;
	else
	{
		//printf("sendto() succeeded !\n");
		printf("----------------------\n");
	}



}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值