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

📄 sdkserver.cpp

📁 INTERNET网络高级编程的包括邮件加密、MAPI、ISAPI、ACTIVEX、FTP等等。
💻 CPP
字号:
// SDKServer.cpp : Defines the entry point for the application.
//

//以下是一些头文件
#include "stdafx.h"

#include "winsock2.h"
#include "stdio.h"
#include "ctype.h"
#include "memory.h"
#include "string.h"
#include "winecho.h"

#define TRUE 1
#define FALSE 0

//一些变量
HANDLE hInst;

char buffer[2];
char *lpBuffer=&buffer[0];

int length=0;

SOCKET s,oldsocket;

int col=0,row=0;

//struct sockaddr_in dest_addr;
unsigned short port=5050;


//函数的声明

BOOL InitWindows(HANDLE);  //[1],实现见[1]
long FAR PASCAL ServerProcedure(HWND,unsigned int,UINT,LONG); //[2],实现见[2]
VOID MessageToUser(HWND,LPSTR);  //[3],实现见[3]
BOOL server(HWND); //[4],实现见[4]
BOOL set_socket(HWND,long); //[5],实现见[5]
BOOL make_socket(HWND); //[6],实现见[6]
BOOL accept_socket(HWND); //[7],实现见[7]
BOOL send_socket(HWND,int); //[8],实现见[8]
BOOL receive_socket(HWND,int *); //[9],实现见[9]
void close_socket(SOCKET); //[10],实现见[10]
void DisplayData(HWND hWnd,int len); //[11],实现见[11]

//Winmain函数
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	HWND hWnd;
	MSG  msg;

    //进行初始化应用程序实例和窗口类
	if (!hPrevInstance)
	{
		if (! InitWindows(hInstance))
			return (FALSE);
	}
    //在这里,只允许有一个服务器在工作
	else 
		return(FALSE);

	hInst=hInstance;

	//创建窗口并且显示它
	hWnd=CreateWindow("ServerClass",
					  "回音程序的服务器",
					  WS_OVERLAPPEDWINDOW,
					  CW_USEDEFAULT,
					  CW_USEDEFAULT,
					  CW_USEDEFAULT,
					  CW_USEDEFAULT,
					  NULL,
					  NULL,
					  hInstance,
					  NULL);
	if (! hWnd)
		return (FALSE);

	ShowWindow(hWnd,nCmdShow);
	UpdateWindow(hWnd);

	EnableMenuItem(GetMenu(hWnd),IDM_EXIT,MF_DISABLED|MF_GRAYED);
	//发送WM_USER消息,以便建立Socket
	PostMessage(hWnd,WM_USER,(WPARAM)0,(LPARAM)0);

	//进入消息循环
	while(GetMessage(&msg,NULL,NULL,NULL))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return (msg.wParam);

}

//实现[1] 初始化和注册窗口类
BOOL  InitWindows(HANDLE hInstance)
{
	WNDCLASS  WndClass;

	WndClass.style=CS_HREDRAW|CS_VREDRAW;
	WndClass.lpfnWndProc=ServerProcedure;
	WndClass.cbClsExtra=0;
	WndClass.cbWndExtra=0;
	WndClass.hInstance=(HINSTANCE)hInstance;
	WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
	WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.lpszMenuName=(LPSTR)"EchoMenu";
	WndClass.lpszClassName=(LPSTR)"ServerClass";
	
	//注册窗口类
	return ( RegisterClass((PWNDCLASS)&WndClass) );
}

//实现[2]是回调函数,见最后一个实现


//实现[3]:给用户输出信息
void MessageToUser(HWND hWnd,LPSTR lpszWarning)
{
	int flag=MessageBox(hWnd,lpszWarning,"Windows Server",
		       MB_OK|MB_ICONINFORMATION);
	if(flag==0)
		MessageBox(hWnd,"fail in messagebox","@@",MB_OK);
}


//实现[4]:服务器创建Socket,同时设置它所关心的事件
BOOL server(HWND hWnd)
{
	//设置菜单项的有效和无效
	EnableMenuItem(GetMenu(hWnd),IDM_START,MF_DISABLED|MF_GRAYED);
	EnableMenuItem(GetMenu(hWnd),IDM_EXIT,MF_ENABLED);

	//创建服务器Socket,见实现[6]
    if (! make_socket(hWnd))
		return (FALSE);

	//设置服务器Socket所关心的事件:客户的请求连接到达,见实现[5]
	if (! set_socket(hWnd,FD_ACCEPT|FD_CLOSE))
		return (FALSE);
	return (TRUE);
}


//实现[5]:设置网络事件函数
BOOL set_socket(HWND hWnd,long lEvent)
{
	//设置网络事件,当事件发生时,将发送UM_SOCK的消息给hWnd窗口
	if(WSAAsyncSelect(s,hWnd,UM_SOCK,lEvent)==SOCKET_ERROR)
	{
		MessageToUser(hWnd,"函数WSAAsyncSelect()出错");
		return(FALSE);
	}
    return(TRUE);
}


//实现[6]:创建Socket、并且进行地址绑定
BOOL make_socket(HWND hWnd)
{
	sockaddr_in sin;
//	unsigned long on=1;

	//建立流式Socket
	s=socket(AF_INET,SOCK_STREAM,0);
	if(s==INVALID_SOCKET)
	{
		MessageToUser(hWnd,"生成Socket出错");
		return(FALSE);
	}

	//以下设置半相关,端口号为5050,IP地址为“202.115.111.222”
	sin.sin_family=AF_INET;
	sin.sin_addr.S_un.S_un_b.s_b1=202;
	sin.sin_addr.S_un.S_un_b.s_b2=115;
	sin.sin_addr.S_un.S_un_b.s_b3=111;
	sin.sin_addr.S_un.S_un_b.s_b4=222;
	sin.sin_port=htons(5050);

	//Bind地址和端口号,成功时,返回的是0
	if( int i=bind(s,(LPSOCKADDR)&sin,sizeof(sin)) )
	{
	    i=WSAGetLastError();
		close_socket(s);
          	
		return(FALSE);
	}

	//让服务器的Socket进行监听,成功的设置成监听状态时,返回的是0
	if(listen(s,5))
		return(FALSE);

	return(TRUE);
}

//实现[7]:接收客户的请求,同时建立一个新的Socket进行请求处理
//而原Socket仍处于监听状态
BOOL accept_socket(HWND)
{
	SOCKET newsocket;
	struct sockaddr tcpaddr;
	int len;

	//建立新的Socket
	len=sizeof(struct sockaddr);
	newsocket=accept(s,(struct sockaddr FAR *)&tcpaddr,(int FAR *)&len);
	if(newsocket==INVALID_SOCKET)
		return(FALSE);
	else
	{
		//保留监听Socket
		//同时为处理新的请求Socket而让s代表新的Socket
		oldsocket=s;
		s=newsocket;
	}
	return(TRUE);
}


//实现[8]:发送数据的处理函数
//关于send函数的参数的含义可以参见1.2.3节
BOOL send_socket(HWND hWnd,int len)
{

	if (send(s,lpBuffer,len,0)==SOCKET_ERROR)
		return (FALSE);
	return(TRUE);
}


//实现[9]:接收数据的处理函数
BOOL receive_socket(HWND hWnd,int *len)
{
	int wantlength,err,reallength;
	
	wantlength=*len;
	//wantlength为打算接收的字节的个数
	//reallength为实际接收的字节的个数
	//关于recv函数的参数的含义可以参见1.2.3节
	if( (reallength=recv(s,lpBuffer,wantlength,0)) == SOCKET_ERROR )
	{
		err=WSAGetLastError();
		//当产生了非WSAEWOULDBLOCK的错误时,则认为接收数据没有成功。
		//而产生了WSAEWOULDBLOCK的错误时,由于此程序中recv()被设置成非了阻塞模式,
		//所以对它的调用将立即返回,同时产生了从错误信息,
		//表示不出现阻塞而立即返回,这时程序可以继续向下运行。
		if( err != WSAEWOULDBLOCK)
			return(FALSE);
	}
	//返回实际接收的字节数
	length=reallength;
	return(TRUE);
}
//实现[10]:关闭Socket函数
void close_socket(SOCKET socket)
{
	(void)closesocket(socket);	
}


//实现[11]:显示客户发来的数据
void DisplayData(HWND hWnd,int len) 
{
	HDC dc;
	int l;
	char line[16];
	
	buffer[len]=0;
	if( dc=GetDC(hWnd) )
	{
		l=wsprintf((LPSTR)line,"%s",lpBuffer);
		TextOut(dc,10*col,16*row,(LPSTR)line,l);
		ReleaseDC(hWnd,dc);
	}

	col+=len;
	if(col>40)
	{
		col=0;
		row++;
	}
}


//回调函数
long FAR PASCAL ServerProcedure(HWND hWnd,
								unsigned message,
								UINT wParam,
								LONG lParam)
{
	WSADATA wsaData;
	int     Status;

	switch(message)
	{
		//分支1:建立和初始化Socket
		case WM_USER:
			//进行版本号的协商
			Status=WSAStartup(0x101,&wsaData);
			if(Status!=0)
			{
				MessageToUser(hWnd,"WSAStartup()函数失败");
				PostQuitMessage(0);
			}
			//确认使用的版本号是1.1
			if( LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1)
			{
				MessageToUser(hWnd,"版本号协商没有成功");
				WSACleanup();
				PostQuitMessage(0);
			}

		
			/*
			//建立和绑定服务器Socket
			if(! server(hWnd))
			{
				MessageToUser(hWnd,"建立和绑定服务器Socket出错");
				//使菜单有效和无效
				EnableMenuItem(GetMenu(hWnd),IDM_START,MF_ENABLED);
				EnableMenuItem(GetMenu(hWnd),IDM_EXIT,MF_DISABLED|MF_GRAYED);
			}
			*/
			
			break;

			
		//分支2:执行菜单命令
		case WM_COMMAND:
			//考虑不同的菜单命令
			switch(wParam)
			{
				case IDM_START:
					//建立和绑定服务器Socket
					if(!server(hWnd))
					{
						MessageToUser(hWnd,"建立和绑定服务器Socket出错");
						//使菜单有效和无效
						EnableMenuItem(GetMenu(hWnd),IDM_START,MF_ENABLED);
						EnableMenuItem(GetMenu(hWnd),IDM_EXIT,MF_DISABLED|MF_GRAYED);
					}
					
					break;

				case IDM_EXIT:
					//退出应用程序
					WSACleanup();
					PostQuitMessage(0);
			
					break;
			}
			break;
		
		//分支3:进行异步事件处理
		case UM_SOCK:
			//考虑不同的异步事件
			switch(lParam)
			{
				//处理连接操作
				case FD_ACCEPT:
					if(! accept_socket(hWnd))
					{
						MessageToUser(hWnd,"接收Socket出错");
						break;
					}

					set_socket(hWnd,FD_READ|FD_CLOSE);
					break;

				//处理读操作
				case FD_READ:
					length=2;
					if(! receive_socket(hWnd,&length) )
					{
						MessageToUser(hWnd,"接收数据出错");
						break;
					}
					
					//在服务器端显示客户传来的数据,调用了DisplayData()函数
					DisplayData(hWnd,length);
				

					//设置下面关心的是写事件的发生
					set_socket(hWnd,FD_WRITE|FD_CLOSE);
					break;

				//处理写操作
				case FD_WRITE:
   				    if(! send_socket(hWnd,length))
					{
						MessageToUser(hWnd,"发送数据出错");
						break;
					}

					//设置下面关心的是读事件的发生
					set_socket(hWnd,FD_READ|FD_CLOSE);
					break;

				/*
				//关闭连接
				case FD_CLOSE:
					if(WSAAsyncSelect(s,hWnd,0,0)==SOCKET_ERROR)
						MessageToUser(hWnd,"事件设置错误");
					MessageToUser(hWnd,"Socket被关闭了");
					EnableMenuItem(GetMenu(hWnd),IDM_START,MF_ENABLED);
					
					break;
				*/
				
				//默认处理
				default:
					if(WSAGETSELECTERROR(lParam)!=0)
					{
						MessageToUser(hWnd,"客户端的应用程序关闭了");
						
						//恢复s成监听Socket
						close_socket(s);
						s=oldsocket;
						//使菜单有效
						EnableMenuItem(GetMenu(hWnd),IDM_START,MF_ENABLED);
					}
			 		break;
			}
			break;

		//分支4:退出应用程序
		case WM_DESTROY:
			WSACleanup();
			PostQuitMessage(0);
			break;

        //分支5:默认消息处理
		default:
			return(DefWindowProc(hWnd,message,wParam,lParam));
	}
 
	return(NULL);
}

⌨️ 快捷键说明

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