TCP/IP基于UDP的可单聊多聊聊天室

fcclient:

1.cpp

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

#include"1.h"
#include"2.h"
char status='A';//状态说明请见main函数
char c;//接收命令选择字符

DWORD WINAPI ThreadRecv(LPVOID lpParam) ;
SendTool *st;
RecvTool *rt;

char Lname[20];//本地登陆用户名
char Lpassword[20];
char qname[20];//请求单聊的用户名
char dname[20];//正在单聊的用户名
char *str;

int main(int argc,char *argv[])
{

	//查参
	if(argc<2){printf("usage:client [server IP address]\n");exit(1);}


	//开启一个接受消息线程
	CreateThread(              
		NULL,              // default security attributes             
		0,                 // use default stack size                
		ThreadRecv,        // thread function               
		0,             // argument to thread function               
		0,                 // use default creation flags               
		NULL);           // returns the thread identifier 

	//开局睡半秒 休息休息 没别的意思
	Sleep(500);

	  st=new SendTool(DEFAULT_PORT,argv[1]);
	//st=new SendTool(DEFAULT_PORT,"127.0.0.1");
	//st.SendMessage("123",3);

	//下面是发送线程 发送线程写在主程序里
	//printf("in the main thread\n");
	printl("*************************************************");
	printl("*                                               *");
	printl("*      欢迎进入计科1202.19-20-21聊天室          *");
	printl("*                                               *");
	printl("*************************************************");
	while(status!='q')
	{
		//A状态:注册、登陆、退出程序
		//B状态:进入群聊,查看在线名单,同xxx单聊,(被请求聊天),退出登陆,退出程序
		//C----:群聊中
		//D----: 单聊中
		switch(status)
		{
		case 'A':
			printl("---------------");
			printl("1.注册");
			printl("2.登陆");
			printl("3.退出程序");
			Scan_c();
			//printf("%c\n",c);
			switch(c)
			{
			case '1':Register();
				break;
			case '2':Login();
				break;	
			case '3':Exit();
				break;		
			default:
				printf("错误输入:%c\n",c);
			}
			break;

		case 'B':
			printl("---------------");
			printl("1.进入聊天室");
			printl("2.查看在线人数");
			printl("3.同XXX单聊");
			printl("4.退出登陆");
			printl("5.刷新");
			Scan_c();
			//printf("%c\n",c);
			switch(c)
			{
			case '1':ChatRoom();
				break;
			case '2':WhoOnLine();
				break;	
			case '3':ChatOne();
				break;		
			case '4':ExitLogin();
				break;
			case '5':continue;
				break;
			default:
				printf("错误输入:%c\n",c);
			}
			break;

		case 'C':
			InChatRoom();
			break;

		case 'D':
			printf("您现在处在单聊状态,您正在同%s进行单聊\n",dname);
			ChatingOne(Lname,dname);
			break;

		case 'E':
			printf("%s向您请求单聊?(y/n)\n",qname);
			Scan_c();

			str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
			memset(str,'\0',sizeof(str));
			strcpy(str,"SE0");
			strcat(str,Lname);
			strcat(str,"#");
			strcat(str,qname);
			strcat(str,"#");

			if(c=='y')
			{
				printf("您同意进行单聊\n");
				status='D';
				str[2]='T';
				strcpy(dname,qname);
				st->mySendMessage(str,strlen(str));
			}
			else
			{
				printf("您拒绝了单聊请求");
				status='B';
				str[2]='F';
				st->mySendMessage(str,strlen(str));
			}
			break;

		//case 'F':
			

		default:
			printf("[-]Error Status!\n");
		}

	}



	return 0;
}


1.h

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

#define DEFAULT_PORT 5051//FOR SEND
#define DEFAULT_PORTRECV 5052//FOR RECV
#define BUFFER_LENGTH 1024

void Delay(int t=1)
{
	Sleep(t*1000);
}
void isErrorMalloc(void *s)
{
	if(!s){printf("[-]Error:Malloc\n");exit(1);}
}
class SendTool
{
private:
	WSADATA wsaData;
	struct sockaddr_in ser;
	int iPort;
	SOCKET sClient;
	int iSend;
public:
	SendTool(int iPort,char *ip)
	{
		this->iPort=iPort;
		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(ip);

		sClient=socket(AF_INET,SOCK_DGRAM,0);
		if(sClient==INVALID_SOCKET)
		{printf("socket()Failed:%d\n",WSAGetLastError());return;}
	}
	void mySendMessage(char *string,int len)
	{

		iSend=sendto(sClient,string,len,0,(SOCKADDR*)&ser,sizeof(ser));
		Delay();
		//	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");
		}
	}
};

//struct MyString
//{
//	char *str;
//	int len;
//};
class RecvTool
{
private:
	WSADATA wsaData;
	struct sockaddr_in cser;
	int iPort;
	SOCKET sClient;
	char *recv_buf;
	int iRecv;
	int iLen;
public:
	char *getRecv_buf(){return recv_buf;};
	int getiRecv(){return iRecv;}

	RecvTool(int iPort)
	{
		this->iPort=iPort;

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

		cser.sin_family=AF_INET;  
		cser.sin_port=htons(DEFAULT_PORTRECV);  
		cser.sin_addr.s_addr=htonl(INADDR_ANY); 

		sClient=socket(AF_INET,SOCK_DGRAM,0);

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

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

		recv_buf=(char *)malloc(sizeof(char)*1020);
	}
	int recv()
	{
		//MyString* ms=(MyString*)malloc(sizeof(MyString));
		//if(!ms)return NULL;
		iLen=sizeof(cser);
		iRecv=recvfrom(sClient,recv_buf,BUFFER_LENGTH,0,(SOCKADDR*)&cser,&iLen);
		if(iRecv==SOCKET_ERROR)
		{printf("recvfrom()Faild:%d\n",WSAGetLastError());return 0;}
		else if(iRecv==0) return 0;
		else 
		{
			//printf("int the recv():iRecv=%d",iRecv);
		recv_buf[iRecv]='\0';
		return 0;
		}


	}
};

void Scan_c()
{	
	char str[10];
	extern char c;
	printf(">");
	scanf("%s",str);
	c=str[0];
	getchar();//吸收回车
}

void printl(char *str)
{
	printf("%s\n",str);
	//putchar(10);//enter
}

void Register()
{
	char *str;
	str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
	memset(str,'\0',sizeof(str));

	char name[20],pwd[20];
	extern SendTool *st;
	printf("姓名:");
	scanf("%s",name);getchar();
	printf("密码:");
	scanf("%s",pwd);getchar();

	strcpy(str,"SA1");
	strcat(str,name);
	strcat(str,"#");
	strcat(str,pwd);
	strcat(str,"#");


	//printf("send:%s\n",str);
	st->mySendMessage(str,strlen(str));
}


void Login()
{;
char *str;
str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
memset(str,'\0',sizeof(str));

char name[20],pwd[20];
extern SendTool *st;
printf("姓名:");
scanf("%s",name);getchar();
printf("密码:");
scanf("%s",pwd);getchar();

strcpy(str,"SA2");
strcat(str,name);
strcat(str,"#");
strcat(str,pwd);
strcat(str,"#");


//printf("send:%s\n",str);
st->mySendMessage(str,strlen(str));

extern char Lname[20];
extern char Lpassword[20];
strcpy(Lname,name);
strcpy(Lpassword,pwd);

}



void Exit()
{
	extern char status;
	status='q';

	/*extern char Lname[20];
	extern char Lpassword[20];
	extern SendTool *st;
	extern char status;
	status='q';

	char *str;
	str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
	memset(str,'\0',sizeof(str));


	strcpy(str,"SA3");
	strcat(str,Lname);
	strcat(str,"#");
	strcat(str,Lpassword);
	strcat(str,"#");


	printf("send:%s\n",str);
	st->mySendMessage(str,strlen(str));;
	*/

}

void ChatRoom()
{
	extern char status;
	status='C';
	extern SendTool *st;

	char *str;
	str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
	memset(str,'\0',sizeof(str));
	extern char Lname[20];
	strcpy(str,"SB1");
	strcat(str,Lname);
	strcat(str,"#");
;
	st->mySendMessage(str,strlen(str));
}
void WhoOnLine()
{
	printl("正在查询在线名单;");

	extern SendTool *st;

	char *str;
	str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
	memset(str,'\0',sizeof(str));
	extern char Lname[20];
	strcpy(str,"SB2");
	strcat(str,Lname);
	strcat(str,"#");
;
	st->mySendMessage(str,strlen(str));

}
void ChatOne()
{
	extern SendTool *st;
	char tname[20];
	printf("请输入你想单聊对象的名字:");
	scanf("%s",tname);

	char *str;
	str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
	memset(str,'\0',sizeof(str));
	extern char Lname[20];
	strcpy(str,"SB3");
	strcat(str,Lname);
	strcat(str,"#");
	strcat(str,tname);
	strcat(str,"#");

	st->mySendMessage(str,strlen(str));
	printf("已经发送您向%s的单聊请求\n",tname);

;
}
void ExitLogin()
{
	
	extern char Lname[20];
	extern char Lpassword[20];
	extern SendTool *st;
	extern char status;
	status='A';

	char *str;
	str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
	memset(str,'\0',sizeof(str));


	strcpy(str,"SB4");
	strcat(str,Lname);
	strcat(str,"#");
	strcat(str,Lpassword);
	strcat(str,"#");


	//printf("send:%s\n",str);
	st->mySendMessage(str,strlen(str));;
	
;
}

void InChatRoom()
{

	printf("->");
	char s[100];
	scanf("%s",s);

	extern char status;
	if(strcmp(s,"exit")==0)
	{
		status='B';
	}

	extern SendTool *st;

	char *str;
	str=(char *)malloc(sizeof(char)*1000);isErrorMalloc((void*)str);
	memset(str,'\0',sizeof(str));

		extern char Lname[20];
	strcpy(str,"SC0");
	strcat(str,Lname);
	strcat(str,"#");
	strcat(str,s);
	strcat(str,"#");

	st->mySendMessage(str,strlen(str));

}



void ChatingOne(char *Lname,char *dname)
{extern char status;
	char str[1000];
	char s[900];
	while(1)
	{
	printf(">");
	scanf("%s",s);getchar();

	strcpy(str,"SD0");
	strcat(str,Lname);
	strcat(str,"#");
	strcat(str,dname);
	strcat(str,"#");
	strcat(str,s);
	strcat(str,"#");
	
	extern SendTool *st;
	if(status=='D')
	st->mySendMessage(str,strlen(str));
	else break;
	if(strcmp("exit",s)==0)
	{
	status='B';
	break;
	}
	}
}

2.h

DWORD WINAPI ThreadRecv(LPVOID lpParam) 
{
	int i,j;
	char name[20];
	char buf[1024];
	extern char qname[20],dname[20];
	char aname[20],bname[20];
	//printf("in the thredRecv\n");
	extern RecvTool *rt;
	rt=new RecvTool(DEFAULT_PORTRECV);
	char *recv;int len;
	extern char status;
	while(1)
	{
		rt->recv();
		recv=rt->getRecv_buf();len=rt->getiRecv();

		//printf("recv:%s\n",recv);

		switch(recv[1])
		{
		case 'A':
			switch(recv[2])
			{
			case '1'://注册回显
				if(recv[3]=='T')printl("注册成功!");
				else printl("注册失败!");
				break;
			case '2':
				if(recv[3]=='T')
				{
					printl("登陆成功!");
					status='B';
				}
				else printl("登陆失败!");
				break;
			}
			break;
		case 'B':
			switch(recv[2])
			{
			case '2':
				printf("在线的人有:\n");
				j=3;
				for(i=3;i<len;i++)
				{
					if(recv[i]!='#')continue;
					recv[i]='\0';
					printf("%s\n",recv+j);
					j=i+1;		
				}		
				break;

			case '3'://被请求单聊
				extern char qname[20];

				//extern SendTool *st;
				//status='E';//闲置状态,保证主程序不会干扰此处同意
				for(i=3;i<len && recv[i]!='#';i++);
				strncpy(qname,recv+3,i-3);name[i-3]='\0';
				status='E';//有被请求的消息
				printf("有人向您请求单聊,请输入5刷新!\n");
				//printf("%s向你请求单聊(y/n)\n>");
				//char temp[10];
				//scanf("%s",temp);
				//if(temp[0]=='y')
				//{
				//	printf("您同意了单聊会话\n");
				//	status='D';
				st->mySendMessage
				//}
				//else
				//{
				//	printf("您拒绝了单聊会话");
				//status='B';
				//}
				break;
			}
			break;
		case 'C':
			int i;
			for(i=3;i<len && recv[i]!='#';i++);
			strncpy(name,recv+3,i-3);name[i-3]='\0';
			strncpy(buf,recv+i+1,len-2-i);buf[len-2-i]='\0';
			printf("%s:%s\n",name,buf);

			break;
		case 'D':
			//printf("iRecv=%d\n",len);
			//printf("recv=%s\n",recv);
			for(i=3;i<len;i++) if(recv[i]=='#') break;   recv[i]='\0';
			strcpy(aname,recv+3);
			j=i+1;
			for(;i<len;i++) if(recv[i]=='#') break;		recv[i]='\0';
			strcpy(bname,recv+j);
			j=i+1;
			for(;i<len;i++) if(recv[i]=='#') break;		recv[i]='\0';
			strcpy(buf,recv+j);
			//printf("debug:aname=%s  bname=%s buf=%s\n",aname,bname,buf);
			if(strcmp("exit",buf)==0)
			{
				printf("对方退出单聊,请输入任意字符按回车刷新");
				status='B';
			}
			else
			{
				printf("%s:%s\n",aname,buf);
				printf(">");
			}
			break;

		case 'E':
			char aname[20],bname[20];
			for(i=3;i<len && recv[i]!='#';i++);
			strncpy(aname,recv+3,i-3);aname[i-3]='\0';
			strncpy(bname,recv+i+1,len-2-i);bname[len-2-i]='\0';
			if(recv[2]=='T')
			{
			printf("%s同意了您的单聊请求,请刷新!\n",aname);
			status='D';
			strcpy(dname,aname);
			}
			else
			{
			printf("%s拒绝了您的单聊请求,刷新也没用!\n");
			}
			break;
		default:

		;
		};



	}


	return 0;
}

fserver:

1.cpp

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

#include"1.h";

Tool *T;
Seq *s=new Seq(MAX_PERSON_NUM);
char name[20];char password[20];
char aname[20];char bname[20];
char *str;
int i,j;
char buf[1024];
int main()
{
	T=new Tool(DEFAULT_PORT,DEFAULT_PORTSEND);
	int t;
	printf("----------------------\n");
	printf("Server Waiting\n");
	printf("----------------------\n");

	char *recv;int len;
	while(1)
	{
		T->recv();
		recv=T->getRecv_buf();len=T->getiRecv();

		printf("recv:%s\t",recv);
		printf("len=%d\n",len);

		switch(recv[1])
		{
		case 'A':
			//发来的消息不是注册 就是登陆 消息格式为 SA1/SA2+NAME+#+PWD+#
			//	首先解析账号密码

			for(i=3;i<len && recv[i]!='#';i++);
			strncpy(name,recv+3,i-3);name[i-3]='\0';
			strncpy(password,recv+i+1,len-2-i);password[len-2-i]='\0';
			printf("name=%s\n",name);
			printf("password=%s\n",password);

			switch(recv[2])
			{
			case '1'://register
				if(!s->isAlive(name))
				{
					//可以注册
					Data * t=new Data();
					strcpy(t->UserName,name);
					strcpy(t->Password,password);
					strcpy(t->Ip,"");
					t->status='Q';

					s->Add(t);

					T->mySendMessage("RA1T",4);

					printf("%s用户注册成功!\n",name);
				}
				else
				{
					//nonono!
					T->mySendMessage("RA1F",4);
					printf("%s用户注册失败!\n",name);
				}

				break;

			case '2'://login

				t=s->correct(name,password);
				if(t!=-1)
				{//you can login
					s->login(t,T->getIp());
					T->mySendMessage("RA2T",4);
					printf("%s用户登陆成功\n",name);
				}
				else
				{
					T->mySendMessage("RA2F",4);
					printf("%s用户登陆失败\n",name);
				}
				break;

				/*case '3':
				t=s->Search(name);
				if(t!=-1)
				{
				s->Delete(t);
				}*/
			}

			break;

		case 'B':


			for(i=3;i<len && recv[i]!='#';i++);
			strncpy(name,recv+3,i-3);name[i-3]='\0';
			printf("name=%s\n",name);

			switch(recv[2])
			{
			case '1':
				//SB1进入多人聊天室
				t=s->Search(name);
				s->SetStatus(t,'C');
				printf("%s进入多人聊天室!\n",name);
				break;
			case '2':
				str=(char *)malloc(sizeof(char)*1000);

				strcpy(str,"RB2");
				strcat(str,s->QueryOnline());

				T->mySendMessage(str,strlen(str));
				printf("已经向%s用户发送在线名单\n",name);

				break;
			case '3':
				char toname[20];
				strncpy(toname,recv+i+1,len-2-i);toname[len-2-i]='\0';	
				printf("%s向%s请求单聊\n",name,toname);
				str=(char *)malloc(sizeof(char)*1000);

				strcpy(str,"RB3");
				strcat(str,name);
				strcat(str,"#");

				t=s->Search(toname);
				if(t!=-1){
					T->mySendMessage(str,strlen(str),s->GetIp(t));
					printf("服务器已经向%s转达被单聊的请求\n",toname);}
				else{
					printf("%s用户不存在,却被请求,发生错误!\n",toname);
				}
				break;

			case '4':
				t=s->Search(name);
				s->SetStatus(t,'Q');
				printf("%s已经退出登陆\n",name);
				break;


			}
			break;

		case 'C':

			for(i=3;i<len && recv[i]!='#';i++);
			strncpy(name,recv+3,i-3);name[i-3]='\0';

			strncpy(buf,recv+i+1,len-2-i);buf[len-2-i]='\0';
			//printf("name=%s\n",name);
			printf("%s用户在聊天室中发了一条消息:%s\n",name,buf);

			if(strcmp("exit",buf)==0)
			{
				t=s->Search(name);
				s->SetStatus(t,'B');
				printf("%s用户退出了聊天室\n",name);			
			}
			else
			{
				int c;
				c=s->Getc();
				for(i=0;i<=c;i++)
				{
					if(s->GetStatus(i)=='C')
					{

						str=(char *)malloc(sizeof(char)*1000);

						strcpy(str,"RC0");
						strcat(str,name);
						strcat(str,"#");
						strcat(str,buf);
						strcat(str,"#");

						T->mySendMessage(str,strlen(str),s->GetIp(i));
						printf("已经向%s用户发送%s消息\n",s->GetName(i),buf);
					}
				}
			}
			break;

		case 'D':
			for(i=3;i<len;i++) if(recv[i]=='#') break;   recv[i]='\0';
			strcpy(aname,recv+3);
			j=i+1;
			for(;i<len;i++) if(recv[i]=='#') break;		recv[i]='\0';
			strcpy(bname,recv+j);
			j=i+1;
			for(;i<len;i++) if(recv[i]=='#') break;		recv[i]='\0';
			strcpy(buf,recv+j);

			if(strcmp("exit",buf)==0)
			{
				s->SetStatus(s->Search(aname),'B');
				s->SetStatus(s->Search(bname),'B');
				printf("%s和%s退出单聊\n",aname,bname);
			}
			printf("%s-->%s:%s\n",aname,bname,buf);
			str=(char *)malloc(sizeof(char)*1000);

			strcpy(str,"RD0");
			strcat(str,aname);
			strcat(str,"#");
			strcat(str,bname);
			strcat(str,"#");
			strcat(str,buf);
			strcat(str,"#");
			//printf("debug:str:%s\n",str);
			//printf("debug:sizeof(str)=%d\n",sizeof(str));
		
			T->mySendMessage(str,strlen(str),s->GetIp(s->Search(bname)));
			//printf("服务器已经向%s转达了这句话!\n",bname);

			break;

		case 'E':
			//a同意或者不同意b的单聊请求
			for(i=3;i<len && recv[i]!='#';i++);
			strncpy(aname,recv+3,i-3);aname[i-3]='\0';
			strncpy(bname,recv+i+1,len-2-i);bname[len-2-i]='\0';
			printf("aname=%s\n",aname);
			printf("bname=%s\n",bname);
			if(recv[2]=='T')
			{
				printf("%s同意%s的单聊请求\n",aname,bname);

				str=(char *)malloc(sizeof(char)*1000);

				strcpy(str,"RET");
				strcat(str,aname);
				strcat(str,"#");
				strcat(str,bname);
				strcat(str,"#");

				T->mySendMessage(str,strlen(str),s->GetIp(s->Search(bname)));

			}
			else
			{
				printf("%s不同意%s的单聊请求\n",aname,bname);
				str=(char *)malloc(sizeof(char)*1000);

				strcpy(str,"REF");
				strcat(str,aname);
				strcat(str,"#");
				strcat(str,bname);
				strcat(str,"#");

				T->mySendMessage(str,strlen(str),s->GetIp(s->Search(bname)));

			}
			break;
		default:
			printf("Error message!\n");


		}

	}

	return 0;
}

1.h

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

#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 1024
#define MAX_PERSON_NUM 100

class Tool
{
private:
	int iPort;
	int iPortsend;
	WSADATA wsaData;
	SOCKET sSocket;
	char *send_buf;
	char *recv_buf;
	struct sockaddr_in ser,cli;
	int iLen;
	int iRecv;
	int iSend;
public:
	char *getRecv_buf(){return recv_buf;};
	int getiRecv(){return iRecv;}
	char *getIp(){return inet_ntoa(cli.sin_addr);}
	Tool(int port,int portsend)
	{
		this->iPort=port;
		this->iPortsend=portsend;

		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);
		iLen=sizeof(ser);

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

		send_buf=(char *)malloc(sizeof(char)*BUFFER_LENGTH);
		recv_buf=(char *)malloc(sizeof(char)*BUFFER_LENGTH);
		memset(recv_buf,'\0',sizeof(recv_buf));
		memset(send_buf,'\0',sizeof(recv_buf));

	}

	int recv()
	{
		//MyString* ms=(MyString*)malloc(sizeof(MyString));
		//if(!ms)return NULL;
		memset(recv_buf,'0',sizeof(recv_buf));

		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) return 0;
		else 
		{
			//printf("in the recv() :%s\n",recv_buf);
			recv_buf[iRecv]='\0';
			return 0;
		}


	}

	void mySendMessage(char *string,int len,char *ip=NULL)
	{
		if(!ip)
		{
			//printf("debug:len=%d\n",len);
		cli.sin_port=htons(iPortsend);
		iSend=sendto(sSocket,string,len,0,(SOCKADDR*)&cli,sizeof(cli));
		//	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");
		}
		}
		else
		{
		cli.sin_port=htons(iPortsend);
		cli.sin_addr.s_addr=inet_addr(ip);
		iSend=sendto(sSocket,string,len,0,(SOCKADDR*)&cli,sizeof(cli));
		//	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");
		}
		
		}

	}
};


typedef struct 
{
	char UserName[20];
	char Password[20];
	char status;//A,B,C,D,Q
	char Ip[20];

}Data;

class Seq
{
private:
	Data** p;
	int len;//最大长度
	int c;//最大的下标
	int num;//人数
public:
	Seq(int l)
	{
		this->len=l;
		p=(Data**)malloc(sizeof(Data*)*len);if(!p)exit(1);
		c=-1;
	}

	void Add(Data *t)
	{
		num++;
		int i;
		for(i=0;i<=c;i++)
		{
			if(p[i]->status=='Q')break;
		}
		if(i==c+1)
		{
			//not find
			c++;
			i=c;		
		}

		p[i]=t;
		//printf("name:%s\n",p[c]->UserName);
		//printf("password:%s",p[c]->Password);

		;
	}

	void Delete(int t)
	{
		p[t]->status='Q';
		num--;
		;
	}

	int Search(char *name=NULL)
	{
		//printf("c=%d\n",c);
		int i;
		if(name)
		{
			for(i=0;i<=c;i++)
			{
				//printf("in the search  :name=%s\n",name);
				//printf("in the search  :username=%s\n",p[i]->UserName);
				if(strcmp(name,p[i]->UserName)==0)return i;
			}

		}


		return -1;
	}

	bool isAlive(char *name=NULL)
	{
		//printf("in the alive  name:%s\n",name);
		return Search(name)!=-1?true:false;
	}

	int correct(char *name=NULL,char *pwd=NULL)
	{
		int i;
		if(name && pwd)
		{
			i=Search(name);
			if(i!=-1)
			{
				if(strcmp(pwd,p[i]->Password)==0)return i;
			}

		}

		return -1;
	}

	void login(int t,char *ip)
	{
		p[t]->status='B';
		strcpy(p[t]->Ip,ip);
		//printf("ip:%s\n",ip);
	}

	void SetStatus(int t,char e)
	{
		p[t]->status=e;
	}
	char GetStatus(int i)
	{
		return p[i]->status;
	}
	int Getc()
	{
		return this->c;
	}
	char *GetIp(int t)
	{
		return p[t]->Ip;
	}
	char *GetName(int t)
	{
		return p[t]->UserName;
	}
	char *QueryOnline()
	{
		char *s;
		s=(char *)malloc(sizeof(char)*950);
		s[0]='\0';
		int i;
		for(i=0;i<=c;i++)
		{
			if(GetStatus(i)=='B')
			{
				strcat(s,GetName(i));
				strcat(s,"#");
			}
		}
		return s;
	}
};


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<计算机网络实验> 基于TCP的网络聊天室的设计 -实验指导 一、实验目的 1.掌握通信规范的制定及实现。 2.练习较复杂的网络编程,能够把协议设计思想应用到现实应用中。 二、实验内容和要求 1.进一步熟悉VC++6编程环境; 2.利用VC++6进行较复杂的网络编程,完成网络聊天室的设计及编写; 三、实验(设计)仪器设备和材料 1.计算机及操作系统:PC机,Windows; 2.网络环境:可以访问互联网; 四、 TCP/IP程序设计基础 基于TCP/IP的通信基本上都是利用SOCKET套接字进行数据通讯,程序一般分为服务器端和用户端两部分。设计思路(VC6.0下): 第一部分 服务器端 一、创建服务器套接字(create)。 二、服务器套接字进行信息绑定(bind),并开始监听连接(listen)。 三、接受来自用户端的连接请求(accept)。 四、开始数据传输(send/receive)。 五、关闭套接字(closesocket)。 第二部分 客户端 一、创建客户套接字(create)。 二、与远程服务器进行连接(connect),如被接受则创建接收进程。 三、开始数据传输(send/receive)。 四、关闭套接字(closesocket)。 CSocket的编程步骤:(注意我们一定要在创建MFC程序第二步的时候选上Windows Socket选项,其中ServerSocket是服务器端用到的,ClientSocket是客户端用的。) (1)构造CSocket对象,如下例: CSocket ServerSocket; CSocket ClientSocket; (2)CSocket对象的Create函数用来创建Windows Socket,Create()函数会自行调用Bind()函数将此Socket绑定到指定的地址上面。如下例: ServerSocket.Create(823); //服务器端需要指定一个端口号,我们用823。 ClientSocket.Create(); //客户端不用指定端口号。 (3)现在已经创建完基本的Socket对象了,现在我们来启动它,对于服务器端,我们需要这个Socket不停的监听是否有来自于网络上的连接请求,如下例: ServerSocket.Listen(5);//参数5是表示我们的待处理Socket队列中最多能有几个Socket。 (4)对于客户端我们就要实行连接了,具体实现如下例: ClientSocket.Connect(CString SerAddress,Unsinged int SerPort);//其中SerAddress是服务器的IP地址,SerPort是端口号。 (5)服务器是怎么来接受这份连接的呢?它会进一步调用Accept(ReceiveSocket)来接收它,而此时服务器端还须建立一个新的CSocket对象,用它来和客户端进行交流。如下例: CSocket ReceiveSocket; ServerSocket.Accept(ReceiveSocket); (6)如果想在两个程序之间接收或发送信息,MFC也提供了相应的函数。如下例: ServerSocket.Receive(String,Buffer); //String是你要发送的字符串,Buffer是发送字符串的缓冲区大小。ServerSocket.Send(String,Butter);//String是你要接收的字符串,Buffer是接收字符串的缓冲区大小。
里面包含聊天室的客户端和服务器端的源文件和一份完整的设计报告。 一、 系统概要 本系统能实现基于VC++的网络聊天室系统。有单独的客户端、服务器端。 服务器应用程序能够接受来自客户端的广播,然后向客户端发送本机的IP与服务端口,让客户端接入到服务器进行聊天,检测用户名是否合法(重复),服务器责接收来自客户端的聊天信息,并根据用户的需求发送给指定的人或所有人,能够给出上线下线提示。客户端能够发出连接请求,能编辑发送信息,可以指定发给单人或所有人,能显示聊天人数,上线下线用户等。 二、 通信规范的制定 服务请求规范: 服务器端: (1) 创建一个UDP的套接字,接受来自客户端的广播请求,当请求报文内容为“REQUEST FOR IP ADDRESS AND SERVERPORT”时,接受请求,给客户端发送本服务器TCP聊天室的端口号。 (2) 创建一个主要的TCP协议的套接字负责客户端TCP连接 ,处理它的连接请求事件。 (3)在主要的TCP连接协议的套接字里面再创建TCP套接字保存到动态数组里,在主要的套接字接受请求后 ,就用这些套接字和客户端发送和接受数据。 客户端: (1) 当用户按“连接”按钮时,创建UDP协议套接字,给本地计算机发广播,广播内容为“REQUEST FOR IP ADDRESS AND SERVERPORT”。 (2)当收到服务器端的回应,收到服务器发来的端口号后,关闭UDP连接。根据服务器的IP地址和端口号重新创建TCP连接。 故我思考:客户端一定要知道服务器的一个端口,我假设它知道服务器UDP服务的端口,通过发广播给服务器的UDP服务套接字,然后等待该套接字发回服务器TCP聊天室服务的端口号,IP地址用ReceiveForom也苛刻得到。 通信规范 通信规范的制定主要跟老师给出的差不多,并做了一小点增加: (增加验证用户名是否与聊天室已有用户重复,在服务器给客户端的消息中,增加标志0) ① TCP/IP数据通信 --- “聊天”消息传输格式 客户机 - 服务器 (1)传输“用户名” STX+1+用户名+ETX (2) 悄悄话 STX+2+用户名+”,”+内容+ETX (3) 对所有人说 STX+3+内容+ETX 服务器- 客户机 (0)请求用户名与在线用户名重复 //改进 STX+0+用户名+EXT (1)首次传输在线用户名 STX+1+用户名+ETX (2)传输新到用户名 STX+2+用户名+ETX (3)传输离线用户名 STX+3+用户名+ETX (4)传输聊天数据 STX+4+内容+ETX (注:STX为CHR(2),ETX 为CHR(3)) 三、 主要模块的设计分析 四、 系统运行效果 (要求有屏幕截图) 五、 心得与体会
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值