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

📄 test.cpp

📁 分别包括客户端和服务端
💻 CPP
字号:
#include "stdafx.h"
#include "test.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CWinApp theApp;
SOCKET server;

using namespace std;

UINT  MTServerThread(LPVOID pParam);
UINT  ClientThread(LPVOID pParam);
BOOL ParseCmd(char *str, CString& cmd, CString& params);
BOOL SendFile(SOCKET s, CString fname);

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	cout << "按下ESC车退出程序\r\n";
	AfxBeginThread(MTServerThread,0);//开启一个MTserver的线程,参数为0
	while(_getch()!=27);
	//关闭server
	closesocket(server);
	//将其从Windows Sockets的实现中注销
	WSACleanup();

	return 0;
}


UINT  MTServerThread(LPVOID pParam)
{		
	WSADATA wsaData;
	sockaddr_in local;
	//指定加载的Winsock库的版本
	int wsaret=WSAStartup(0x101,&wsaData);
	//调用成功则函数返回0
	//调用失败,程序退出
	if(wsaret!=0)
	{
		return 0;
	}
	local.sin_family=AF_INET;
	local.sin_addr.s_addr=INADDR_ANY;//使用自己的ip
	local.sin_port=htons((u_short)22222);
	//创建我们的socket套接字
	server=socket(AF_INET,SOCK_STREAM,0);
	//如果socket()函数调用失败,退出
	if(server==INVALID_SOCKET)
	{
		return 0;
	}
	//建立socket的本地关联
	if(bind(server,(sockaddr*)&local,sizeof(local))!=0)
	{
		return 0;
	}
	//进入监听状态
	//指定backlog值为10
	if(listen(server,10)!=0)
	{
		return 0;
	}

	//客户端套接字的变量
	SOCKET client;
	sockaddr_in from;
	int fromlen=sizeof(from);

	while(true)
	{
		//接受客户端连接
		client=accept(server,
			(struct sockaddr*)&from,&fromlen);
		AfxBeginThread(ClientThread,(LPVOID)client);	
	}	

	return 0;
}

UINT  ClientThread(LPVOID pParam)
{
	//定义命令缓存,命令与参数字符串
	char buff[512];
	char temp;
	CString cmd;
	CString params;
	int n;
	int x;
	

	BOOL key=false;
	SOCKET client=(SOCKET)pParam;
	//把"#服务器就绪,请输入指令"放入缓存中
	strcpy(buff,"#服务器就绪,请输入指令.\r\n");
	//在客户端显示出来
	send(client,buff,strlen(buff),0);
	//进入死循环
	while(true)
	{   
		int i = 1;
		//读取用户输入的字符串以回车结束,并把他们放到缓存中去
		//
		n=recv(client,buff,512,0);
		if(buff[0]=='-')
		{
		
			while(buff[i-1]!='\n')
			{
				n=recv(client,buff+i,1,0);
				i++;
			}
	
	
			buff[i]='\0';
		
			int j=1;
			while(j<i)
			{
				temp=buff[j];
				buff[j-1]=temp;
				j=j+1;
			}
		}
		else{
			if(n==SOCKET_ERROR )			
			break;
		    buff[n]='\0';
		}
		//解析命令代码是否成功
		if(ParseCmd(buff,cmd,params))
		{	
			//如果命令代码是"QUIT",则退出
			if(cmd=="QUIT")
				break;
			//命令是否是"KEY"
			if(cmd=="KEY")
			{
				//如果是,那空格后的参数是否是"passwd"
				if(params=="passwd")
				{
					//如果是
					key=true;
					//把提示信息放入缓存.
					strcpy(buff,"#密码正确,您已经登录.\r\n");
				}
				else
				{
					strcpy(buff,"!密码错误!\r\n");
				}
				//把以上信息在客户端显示出来.
				send(client,buff,strlen(buff),0);
			}
			if(cmd=="FILE")
			{
				//如果登录
				if(key)
				{
					//文件传输
					if(SendFile(client,params))
						sprintf(buff,"#File %s 成功打开.\r\n",params);
					else
						sprintf(buff,"!File %s 打开失败.\r\n",params);
					x=send(client,buff,strlen(buff),0);					
				}
				else
				{
					strcpy(buff,"!对不起,你没有登录,请输入密码.\r\n");
					send(client,buff,strlen(buff),0);
				}
			}
		}
		else
		{
			//输入指令有误
			strcpy(buff,"!你输入的指令有误.\r\n");
			send(client,buff,strlen(buff),0);
		}
	}		

	closesocket(client);
	return 0;
}

//指令解析子程序
BOOL ParseCmd(char *str, CString& cmd, CString& params)
{
	int n;
	CString tmp=str;
	//去掉指令头尾的空格,回车或tab.
	tmp.TrimLeft();
	tmp.TrimRight();
	//以中间的空格为界,分离前后的命令
	if((n=tmp.Find(' '))==-1)
	{
		tmp.MakeUpper();
		if(tmp!="QUIT")
			return false;
		cmd=tmp;
		return true;
	}		
	cmd=tmp.Left(n);
	params=tmp.Mid(n+1);
	cmd.MakeUpper();
	if((cmd!="KEY") && (cmd!="FILE"))
		return false;
	return true;
}

//文件传输
BOOL SendFile(SOCKET s, CString fname)
{	
	CFile f;
	CFile cf;

	//打开文件,属性为只读
	BOOL p=f.Open(fname,CFile::modeRead);
	char buff[1024];
	int y;
	int x;
	int z;
	if(!p)
		return false;
	while(true)
	{	
		//读取1024个字
		y=f.Read(buff,1024);
	
		//发送到缓冲区
		x=send(s,buff,y,0);
		//如果读取得不到1024字,就关闭文件
		if(y<1024)
		{
			f.Close();
			break;
		}			
	}	

	return true;
}

⌨️ 快捷键说明

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