📄 netmsgserverdlg.cpp
字号:
// 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 + -