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

📄 netmsgserverdlg.cpp

📁 这是聊天系统的服务器端
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// NetMsgServerDlg.cpp : implementation file
//

#include "stdafx.h"
#include "NetMsgServer.h"
#include "NetMsgServerDlg.h"
#include <odbcinst.h>

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

#define WM_ICON_NOTIFY WM_USER+10

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
#define DATA_BUFSIZE   1024
#define MAX_BUFF_SIZE  1024
#define MAX_NAME_LEN   128
#define MAX_PWD_LEN    128
#define MAX_ONLINE_NUM 50
#define MAX_REQ_LEN    256

#define WSA_RECV 0
#define WSA_SEND 1

#define LOGGED_IN       230
#define LOGIN_FAILED_AT_PWD   231
#define LOGIN_FAILED_AT_ID   232
#define LOGIN_FAILED_TOOMANY_ONLINEUSER 233
#define LOGIN_FAILED_BECAUSE_LOGAGAIN   234
#define LOGIN_FAILED_BECAUSE_DB 235

#define UPDATE_SUCCESS 240
#define UPDATE_FAIL    241     

#define REGT_SUCCESS   250
#define REGT_FAIL_BECAUSE_DBREAD 251
#define REGT_FAIL_BECAUSE_DBWRITE 252

#define NETMSG_QUIT     221

#define SERVER_PORT 4000

typedef struct
{
	char buffRecv[DATA_BUFSIZE];
	char buffSend[DATA_BUFSIZE];
	WSABUF wsaBuf;
	SOCKET s;
	WSAOVERLAPPED o;
	DWORD dwBytesSend;
	DWORD dwBytesRecv;
	int nStatus;
	char ip[16];
	BOOL bLoggedIn;
}SOCKET_INF,*LPSOCKET_INF;

//保存在线用户的结构
typedef struct
{
	long id; //用户id    
	char nickname[20];
	char ip[16]; //用户的IP地址
	LPSOCKET_INF pSI; 
}ONLINEUSER_INF,*LPONLINEUSER_INF;

//用户信息的结构
typedef struct
{
	long id;
	char nickname[20];
	char sex[10];
	int age;
	char address[50];
	char password[20];
}USER_INF,*LPUSER_INF;

//全局变量
DWORD g_dwEventTotal;
DWORD g_index;
WSAEVENT g_events[WSA_MAXIMUM_WAIT_EVENTS];

LPSOCKET_INF g_sockets[WSA_MAXIMUM_WAIT_EVENTS];
CRITICAL_SECTION g_cs; 

SOCKET g_serverSocket;
DWORD g_dwListCount;

ONLINEUSER_INF g_onlineUser[MAX_ONLINE_NUM];
DWORD g_ouIndex;



//全局函数
DWORD WINAPI ProcessThreadBegin(LPVOID lpParameter);
DWORD WINAPI ProcessThreadIO(LPVOID lpParameter);

int SendRes( LPSOCKET_INF pSI );
int RecvReq( LPSOCKET_INF pSI );
int LoginIn(LPSOCKET_INF pSI);
void GetOnlineList(LPSOCKET_INF pSI);
int DealCommand( LPSOCKET_INF pSI );
void PrintSystemError(CString str);
int RegisterUserInfo( LPSOCKET_INF pSI );

//服务器命令一览表
//USER id
//PASS pwd
//LIST
class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNetMsgServerDlg dialog

CNetMsgServerDlg::CNetMsgServerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CNetMsgServerDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CNetMsgServerDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_pSet = &m_set;
}

void CNetMsgServerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CNetMsgServerDlg)
	DDX_Control(pDX, IDC_LIST1, m_list);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CNetMsgServerDlg, CDialog)
	//{{AFX_MSG_MAP(CNetMsgServerDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_SERVER_BEGIN, OnServerBegin)
	ON_BN_CLICKED(IDC_SERVER_STOP, OnServerStop)
	ON_WM_CLOSE()
	ON_COMMAND(ID_TRAY_RESTORE, OnTrayRestore)
	ON_COMMAND(ID_TRAY_EXIT, OnTrayExit)
	ON_MESSAGE(WM_ICON_NOTIFY, OnTrayNotification)
	ON_COMMAND(ID_ABOUTNETMSG, OnAboutnetmsg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNetMsgServerDlg message handlers

BOOL CNetMsgServerDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	// TODO: Add extra initialization here

	g_dwListCount = 0;

   // 自动配置数据源

    CString sPath;
	GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
	sPath.ReleaseBuffer ();
	int nPos;
	nPos=sPath.ReverseFind ('\\');
	sPath=sPath.Left (nPos);
	//nPos=sPath.ReverseFind('\\');
	//sPath=sPath.Left (nPos);
	CString lpszFile =sPath+ "\\netmsg.mdb";

    char* szDesc;
	int mlen;
	szDesc=new char[256];
	sprintf(szDesc,"DSN=%s? DESCRIPTION=TOC support source? DBQ=%s? FIL=MicrosoftAccess? DEFAULTDIR=%s?? ","netmsg",lpszFile,sPath);

	mlen = (int)strlen(szDesc);
    for (int i=0; i<mlen; i++)
	{
	if (szDesc[i] == '?')
	 szDesc[i] = '\0';
	}

    if (FALSE == SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)\0",(LPCSTR)szDesc))
    AfxMessageBox("SQLConfigDataSource Failed");

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CNetMsgServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{

			
		CDialog::OnSysCommand(nID, lParam);
	}
	if(nID == SC_MINIMIZE)
	{
		m_trayIcon.Create(this,WM_ICON_NOTIFY,"NetMsg服务器端程序",m_hIcon,IDR_MENU_TRAY); //构造
		ShowWindow(FALSE); //隐藏窗口
	}

}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CNetMsgServerDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CNetMsgServerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CNetMsgServerDlg::OnServerBegin() 
{
	// TODO: Add your control notification handler code here
	DWORD dwThreadID;
	WSADATA wsaData;
	int nRet;



	m_myDlg = this;
	InitializeCriticalSection(&g_cs);
	//启动winsocket2
	if ((nRet = WSAStartup(0x0202,&wsaData)) != 0 )
	{
		AfxMessageBox("错误:WSAStartup failed with error %d\n", nRet);
		return;
	}
	if(wsaData.wVersion != 0x0202)
	{
		AfxMessageBox("错误:WSAStartup failed with error %d\n", nRet);
		return;
	}
	HANDLE h_Handle;
	//创建处理线程
	if((h_Handle = CreateThread(NULL,0,ProcessThreadBegin,NULL,0,&dwThreadID))==NULL)
	{
		AfxMessageBox("错误:WSACreateEvent failed with error %d\n", WSAGetLastError());
		return;
	}
	CloseHandle(h_Handle);

}


//接受client连接
DWORD WINAPI ProcessThreadBegin(LPVOID lpParameter)
{

	SOCKET sListen, sAccept;
	SOCKADDR_IN inetAddr;

	DWORD dwRecvBytes;
	DWORD dwFlags;
	DWORD dwThreadID;
	CNetMsgServerDlg *dlg=(CNetMsgServerDlg*) AfxGetApp()->GetMainWnd();
	
	char temp[20];
	g_ouIndex = 0;
	
	//创建socket
	if((sListen=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
	{
		AfxMessageBox("错误:create socket");
		WSACleanup();
		return -1;
	}	
	
	//邦定主机地址
	inetAddr.sin_addr.s_addr=htonl(INADDR_ANY);
	inetAddr.sin_family=AF_INET;
	inetAddr.sin_port=htons(SERVER_PORT);

	if(bind(sListen,(SOCKADDR*)&inetAddr,sizeof(inetAddr)) ==SOCKET_ERROR)
	{
		AfxMessageBox("错误:bind in start");
		WSACleanup();
		return -1;
	}
	
	
	
	//侦听
	if(listen(sListen,5)!=0)
	{
		AfxMessageBox("错误:listen failed in start");
		return -1;
	}
	g_serverSocket = sListen;
	
	dlg->m_list.InsertString(g_dwListCount++, "创建服务器成功");
	dlg->m_list.SetTopIndex(g_dwListCount-1);
	dlg->GetDlgItem(IDC_SERVER_BEGIN)->EnableWindow(FALSE);

	//创建一个client
	if ((sAccept = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
		WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) 
	{
		PrintSystemError("不能创建sAccept");
		return -1;
	}
	

	//创建第一个手动重置对象 
	if((g_events[0]=WSACreateEvent())==WSA_INVALID_EVENT)
	{

		PrintSystemError("不能创建 g_event[0]");
		return -1;
	}

	//创建处理线程
	HANDLE h_Handle;
	if((h_Handle =CreateThread(NULL,0,ProcessThreadIO,NULL,0,&dwThreadID))==NULL)
	{

		PrintSystemError("不能创建线程");
		return -1;
	}
	
    
	//接受各个client的连接
    g_dwEventTotal = 1;
	while(TRUE)
	{
		//接受侦听
		
		int sockLen = sizeof(inetAddr);

		if((sAccept=accept(sListen,(SOCKADDR*)&inetAddr,&sockLen))==INVALID_SOCKET)
		{
			PrintSystemError("不能接受socket accept连接请求");
			return -1;
		}
		
		sprintf(temp,"%s连接",inet_ntoa(inetAddr.sin_addr));
		dlg->m_list.InsertString(g_dwListCount++, temp);	

		//操作临界区,防止出错
		EnterCriticalSection(&g_cs);

		//创建一个新的SOCKET_INF结构处理接受的数据socket.
		if((g_sockets[g_dwEventTotal]=(LPSOCKET_INF)
			GlobalAlloc(GPTR,sizeof(SOCKET_INF)))==NULL)
		{
			PrintSystemError("GlobalAlloc()失败");
			return -1;
		} 

		//初始化新的SOCKET_INF结构
		char buff[DATA_BUFSIZE];
		memset( buff,0,DATA_BUFSIZE );
		g_sockets[g_dwEventTotal]->wsaBuf.buf=buff;
		g_sockets[g_dwEventTotal]->wsaBuf.len=sizeof(buff);
		g_sockets[g_dwEventTotal]->s=sAccept;
		memset(&(g_sockets[g_dwEventTotal]->o),0,sizeof(OVERLAPPED));
		g_sockets[g_dwEventTotal]->dwBytesSend=0;
		g_sockets[g_dwEventTotal]->dwBytesRecv=0;
		g_sockets[g_dwEventTotal]->nStatus = WSA_RECV;    // 接收
		g_sockets[g_dwEventTotal]->bLoggedIn = FALSE;
		strcpy(g_sockets[g_dwEventTotal]->ip,inet_ntoa(inetAddr.sin_addr));

		//创建事件
		if((g_sockets[g_dwEventTotal]->o.hEvent=g_events[g_dwEventTotal]=
			WSACreateEvent())==WSA_INVALID_EVENT)
		{
			PrintSystemError("WSACreateEvent()失败");
			return -1;
		}

		//发出接受请求
		dwFlags=0;
		if(WSARecv(g_sockets[g_dwEventTotal]->s,&(g_sockets[g_dwEventTotal]->wsaBuf),
			1,&dwRecvBytes,&dwFlags,&(g_sockets[g_dwEventTotal]->o),NULL)==SOCKET_ERROR)
		{
			if (WSAGetLastError() != ERROR_IO_PENDING)
			{
				PrintSystemError("WSARecv()失败");
				return -1;
			}
		}
		
		g_dwEventTotal++;
		
		LeaveCriticalSection(&g_cs);
		//使第一个事件有信号。使工作者线程处理其他的事件		
		if(WSASetEvent(g_events[0])==FALSE)
		{
			PrintSystemError("WSASetEvent()失败");
			WSACleanup();
			return -1;
		}
	
	}

	return 0;
}

//处理命令
DWORD WINAPI ProcessThreadIO(LPVOID lpParameter)
{
	LPSOCKET_INF pSI,pSI_OU;
	DWORD dwBytesTransferred;
	DWORD dwFlags;
	DWORD i;
	CNetMsgServerDlg *dlg=(CNetMsgServerDlg*) AfxGetApp()->GetMainWnd();
	char temp[40];

	while(TRUE)
	{

		if((g_index=WSAWaitForMultipleEvents(g_dwEventTotal,g_events,FALSE,WSA_INFINITE,
			FALSE))==WSA_WAIT_FAILED)
		{
			return 0;
		}
		

		if ((g_index - WSA_WAIT_EVENT_0) == 0)
		{
			WSAResetEvent(g_events[0]);
			continue;
		}
		pSI=g_sockets[g_index-WSA_WAIT_EVENT_0];
		WSAResetEvent(g_events[g_index-WSA_WAIT_EVENT_0]);
		
		//取得传送的字节数
		if(WSAGetOverlappedResult(pSI->s, &(pSI->o), &dwBytesTransferred,FALSE, &dwFlags) ==
			FALSE || dwBytesTransferred==0)
		{
			memset(temp,0,sizeof(temp));
			sprintf(temp,"%s断开",pSI->ip);
			dlg->m_list.InsertString(g_dwListCount++, temp);
			dlg->m_list.SetTopIndex(g_dwListCount-1);

			if(pSI->s != INVALID_SOCKET)
			{
				closesocket(pSI->s);
			}
			pSI_OU = pSI;
			GlobalFree(pSI);
			WSACloseEvent(g_events[g_index-WSA_WAIT_EVENT_0]);

            //重新排列sockets,删除已经退出的socket
			if(g_index - WSA_WAIT_EVENT_0 + 1 != g_dwEventTotal)//如果不是最后一个socket
			{
				for(i = g_index - WSA_WAIT_EVENT_0; i < g_dwEventTotal; i++)
				{
					g_sockets[i]=g_sockets[i+1];
					g_events[i]=g_events[i+1];
				}
			}

⌨️ 快捷键说明

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