📄 serverview.cpp
字号:
// ServerView.cpp : implementation of the CServerView class
//
#include "stdafx.h"
#include "Server.h"
#include "ServerDoc.h"
#include "ServerView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CServerView
IMPLEMENT_DYNCREATE(CServerView, CScrollView)
BEGIN_MESSAGE_MAP(CServerView, CScrollView)
//{{AFX_MSG_MAP(CServerView)
ON_COMMAND(ID_SERVER_CLOSE, OnServerClose)
ON_COMMAND(ID_SERVER_OPEN, OnServerOpen)
ON_UPDATE_COMMAND_UI(ID_SERVER_OPEN, OnUpdateServerOpen)
ON_UPDATE_COMMAND_UI(ID_SERVER_CLOSE, OnUpdateServerClose)
//}}AFX_MSG_MAP
// START CUSTOM CODE: Server Code
ON_MESSAGE(WM_SERVER_ACCEPT, OnServerAccept)
ON_MESSAGE(WM_CLIENT_READ, OnClientRead)
ON_MESSAGE(WM_CLIENT_READCLOSE, OnClientReadClose)
// END MODIFICATIONS: Server Code
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerView construction/destruction
CServerView::CServerView()
{
// TODO: add construction code here
m_bServerIsOpen = FALSE;
for(int i=0;(i<MAXClient);i++) m_aClientSocket[i]=INVALID_SOCKET;
}
CServerView::~CServerView()
{
if (m_bServerIsOpen)
closesocket(m_pDoc->m_hServerSocket);
for(int i=0;i<MAXClient;i++)
{
if (m_aClientSocket[i] != INVALID_SOCKET)
{
closesocket(m_aClientSocket[i]);
m_aClientSocket[i] = INVALID_SOCKET;
}
}
}
BOOL CServerView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CScrollView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CServerView drawing
void CServerView::OnDraw(CDC* pDC)
{
CServerDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
TEXTMETRIC tm;
int iYValue;
pDC->GetTextMetrics(&tm);
iYValue = 0;
for (int iLine = 0; iLine <= m_pDoc->m_lLineNumber; iLine++)
{
pDC->TextOut(0,iYValue, m_pDoc->m_csText[iLine], m_pDoc->m_csText[iLine].GetLength());
iYValue += tm.tmHeight;
}
SetScrollSizes(MM_TEXT, CSize(0, ((int) m_pDoc->m_lLineNumber+1) * tm.tmHeight));
return;
}
void CServerView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100;
SetScrollSizes(MM_TEXT, sizeTotal);
m_pDoc = GetDocument();
m_pDoc->SetTitle("Server");
m_pParentWnd = GetParent();
m_pParentMenu = m_pParentWnd->GetMenu();
// Setup the server window
TEXTMETRIC tm;
CRect rectServerSize;
CClientDC dc(this);
dc.GetTextMetrics(&tm);
SetScrollSizes( MM_TEXT, CSize(0,0), CSize(0,(MAX_LINES*tm.tmHeight)), CSize(0, tm.tmHeight));
GetWindowRect( rectServerSize );
GetParentFrame()->MoveWindow( rectServerSize.left, rectServerSize.top, (MAX_COLUMNS*tm.tmAveCharWidth), (24*tm.tmHeight), TRUE);
return;
}
/////////////////////////////////////////////////////////////////////////////
// CServerView diagnostics
#ifdef _DEBUG
void CServerView::AssertValid() const
{
CScrollView::AssertValid();
}
void CServerView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
CServerDoc* CServerView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CServerDoc)));
return (CServerDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CServerView message handlers
void CServerView::PrintString(CString csString)
{
if (csString.GetLength() == 0)
return;
// Print each character in the string except the last one
for (int iChar = 0; iChar < (csString.GetLength()-1); iChar++)
PrintChar(csString[iChar], FALSE); // Don't update scroll bar
// Update the scroll bar when reaching the last character
PrintChar(csString[iChar], TRUE);
m_pDoc->UpdateAllViews(NULL, 0L, 0);
return;
}
void CServerView::PrintString(LPSTR lpszString)
{
if (*lpszString == NULL)
return;
// Print each character in the string except the last one
for (int iChar = 0; lpszString[iChar+1] != NULL; iChar++)
PrintChar(lpszString[iChar], FALSE); // Don't update scroll bar
// Update the scroll bar when reaching the last character
PrintChar( lpszString[iChar], TRUE);
m_pDoc->UpdateAllViews(NULL, 0L, 0);
return;
}
void CServerView::PrintChar(char chChar, BOOL bLastChar)
{
// Ignore carriage-returns, the following statements detect new-lines.
if (chChar =='\r')
return;
CClientDC dc(this);
TEXTMETRIC tm;
CPoint pt, ptOrigin;
CRect rectServerSize;
OnPrepareDC(&dc);
dc.GetTextMetrics(&tm);
if (chChar =='\n')
{
// Move to column zero for a new line.
m_pDoc->m_lColumnNumber = 0;
if (m_pDoc->m_lLineNumber == (MAX_LINES-1))
{
for (int iLine = 0; iLine < MAX_LINES; iLine++)
m_pDoc->m_csText[iLine] = m_pDoc->m_csText[iLine+1];
m_pDoc->m_csText[iLine].Empty();
m_pDoc->UpdateAllViews(this, 0L, 0);
}
else
m_pDoc->m_lLineNumber++;
SetScrollSizes( MM_TEXT, CSize(0, ((int) m_pDoc->m_lLineNumber+1) * tm.tmHeight));
}
else
{
if (m_pDoc->m_lColumnNumber++ >= MAX_COLUMNS)
{
m_pDoc->m_lColumnNumber = 1;
if (m_pDoc->m_lLineNumber == (MAX_LINES-1))
{
for (int iLine = 0; iLine < MAX_LINES; iLine ++)
m_pDoc->m_csText[iLine] = m_pDoc->m_csText[iLine+1];
m_pDoc->m_csText[iLine].Empty();
m_pDoc->UpdateAllViews(this, 0L, 0);
}
else
m_pDoc->m_lLineNumber++;
}
m_pDoc->m_csText[m_pDoc->m_lLineNumber] += chChar;
if (bLastChar)
dc.TextOut(0, (int) m_pDoc->m_lLineNumber * tm.tmHeight,
m_pDoc->m_csText[m_pDoc->m_lLineNumber],
m_pDoc->m_csText[m_pDoc->m_lLineNumber].GetLength());
}
// If last character then update the position on the scroll bar
if (bLastChar)
{
pt = GetScrollPosition();
if ((int) m_pDoc->m_lLineNumber * tm.tmHeight < pt.y)
{
pt.y = (int) m_pDoc->m_lLineNumber * tm.tmHeight;
ScrollToPosition(pt);
}
else
{
CScrollView::GetClientRect( rectServerSize);
if ((((int)m_pDoc->m_lLineNumber * tm.tmHeight) + tm.tmHeight) > rectServerSize.bottom)
{
ptOrigin = dc.GetViewportOrg();
pt.x = ptOrigin.x;
pt.y = ((int) m_pDoc->m_lLineNumber * tm.tmHeight) + tm.tmHeight - rectServerSize.bottom;
ScrollToPosition(pt );
}
}
}
return;
}
void CServerView::ReportWinsockErr(LPSTR lpszErrorMsg)
{
wsprintf(m_chMsgBuffer, "\nWinsock error %d: %s\n\n", WSAGetLastError(), lpszErrorMsg);
PrintString("==>>");
PrintString((LPSTR)lpszErrorMsg);
// MessageBeep(MB_ICONSTOP);
MessageBox(m_chMsgBuffer, AfxGetAppName(), MB_OK|MB_ICONSTOP);
return;
}
/////////////////////////////////////////////////////////////////////////////
// CServerView message handlers
LRESULT CServerView::OnServerAccept(WPARAM wParam, LPARAM lParam)
{
int iErrorCode;
int nLength = sizeof(SOCKADDR);
int i;
if (WSAGETSELECTERROR(lParam))
{
ReportWinsockErr("Error detected on entry into OnServerAccept.");
return 0L;
}
if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT)
{
for(i=0;(i<MAXClient)&&(m_aClientSocket[i]!=INVALID_SOCKET);i++) ;
if(i==MAXClient) return 0L;
// PrintString("==>>一个客户连接成功!\n");
m_aClientSocket[i] = accept(m_pDoc->m_hServerSocket, (LPSOCKADDR)&m_sockClientAddr, (LPINT)&nLength);
if (m_aClientSocket[i] == INVALID_SOCKET)
{
ReportWinsockErr("Server socket failed to accept connection.");
return 0L;
}
CString csDottedDecimal = "一个客户进行了连接 ";
csDottedDecimal += inet_ntoa(m_sockClientAddr.sin_addr);
csDottedDecimal += "\n";
PrintString("==>>"+csDottedDecimal);
WSAAsyncSelect(m_aClientSocket[i],m_hWnd,WM_CLIENT_READCLOSE,FD_READ|FD_CLOSE);
CString csText = "服务器连接成功";
LPSTR lpszResponse = csText.GetBuffer(1000);
iErrorCode = send( m_aClientSocket[i], lpszResponse, lstrlen(lpszResponse), NO_FLAGS);
if (iErrorCode == SOCKET_ERROR)
ReportWinsockErr("Error sending response to client.");
//else
// PrintString("Response sent!\n");
//OnClientClose();
}
return 0L;
}
void CServerView::OnServerClose()
{
char csText[20] = "服务器关闭";
for(int j=0;(j<MAXClient)&&(m_aClientSocket[j]!=INVALID_SOCKET);j++) ;
int jErrorCode = send( m_aClientSocket[j], csText, sizeof(csText), NO_FLAGS);
OnServerBroadcast(csText);
for(int i=0;i<MAXClient;i++)
{
if (m_aClientSocket[i] != INVALID_SOCKET)
{
closesocket(m_aClientSocket[i]);
m_aClientSocket[i] = INVALID_SOCKET;
}
}
closesocket(m_pDoc->m_hServerSocket);
m_bServerIsOpen = FALSE;
PrintString("\n==>>聊天室服务器关闭.\n");
return;
}
void CServerView::OnServerOpen()
{
WSADATA wsaData;
int iErrorCode;
char chLocalInfo[64];
if (WSAStartup(WINSOCK_VERSION, &wsaData))
{
MessageBeep(MB_ICONSTOP);
MessageBox("Winsock could not be initialized!", AfxGetAppName(), MB_OK|MB_ICONSTOP);
WSACleanup();
return;
}
else
WSACleanup();
if (gethostname(chLocalInfo, sizeof(chLocalInfo)))
{
ReportWinsockErr("\nCould not resolve local host!\nAre you on-line?\n");
return;
}
CString csWinsockID = "\n==>>服务器已经开启,端口号: ";
csWinsockID += itoa(m_pDoc->m_nServerPort, chLocalInfo, 10);
csWinsockID += "\n";
csWinsockID += wsaData.szDescription;
csWinsockID += "\n";
PrintString(csWinsockID);
m_pDoc->m_hServerSocket = socket(PF_INET, SOCK_STREAM, DEFAULT_PROTOCOL);
if (m_pDoc->m_hServerSocket == INVALID_SOCKET)
{
ReportWinsockErr("Could not create server socket.");
return;
}
m_pDoc->m_sockServerAddr.sin_family = AF_INET;
m_pDoc->m_sockServerAddr.sin_addr.s_addr = INADDR_ANY;
m_pDoc->m_sockServerAddr.sin_port = htons(m_pDoc->m_nServerPort);
if (bind(m_pDoc->m_hServerSocket, (LPSOCKADDR)&m_pDoc->m_sockServerAddr, sizeof(m_pDoc->m_sockServerAddr)) == SOCKET_ERROR)
{
ReportWinsockErr("Could not bind server socket.");
return;
}
iErrorCode = WSAAsyncSelect(m_pDoc->m_hServerSocket, m_hWnd, WM_SERVER_ACCEPT, FD_ACCEPT);
if (iErrorCode == SOCKET_ERROR)
{
ReportWinsockErr("WSAAsyncSelect failed on server socket.");
return;
}
if (listen(m_pDoc->m_hServerSocket, QUEUE_SIZE) == SOCKET_ERROR)
{
ReportWinsockErr("Server socket failed to listen.");
m_pParentMenu->EnableMenuItem(ID_SERVER_OPEN, MF_ENABLED);
return;
}
PrintString("==>>服务器套接字初始化完成 -- 等待连接.\n\n");
m_bServerIsOpen = TRUE;
return;
}
LRESULT CServerView::OnClientRead(WPARAM wParam, LPARAM lParam)
{
int iBytesRead;
int iBufferLength;
int iEnd;
int iSpaceRemaining;
char chIncomingDataBuffer[1024];
int i;
for(i=0;(i<MAXClient)&&(m_aClientSocket[i]!=wParam);i++)
{
}
if(i==MAXClient) return 0L;
iBufferLength = iSpaceRemaining = sizeof(chIncomingDataBuffer);
iEnd = 0;
iSpaceRemaining -= iEnd;
iBytesRead = recv(m_aClientSocket[i], (LPSTR)(chIncomingDataBuffer+iEnd), iSpaceRemaining, NO_FLAGS);
iEnd+=iBytesRead;
if (iBytesRead == SOCKET_ERROR)
ReportWinsockErr("OnClientRead recv reported a socket error. ");
chIncomingDataBuffer[iEnd] = '\0';
if (lstrlen(chIncomingDataBuffer) != 0)
{
PrintString(chIncomingDataBuffer);
OnServerBroadcast(chIncomingDataBuffer);
}
else
;
// Since Windows send notification of FD_READ and FD_CLOSE,
// assume the client has closed the connection if zero bytes
// are received. The program uses a blocking socket, which means if the
// connection were still open, recv() would wait for data.
//OnClientClose();
return(0L);
}
LRESULT CServerView::OnClientClose(WPARAM wParam, LPARAM lParam)
{
int iErrorCode,i;
if (WSAGETASYNCERROR(lParam))
ReportWinsockErr("Error detected on entry into OnClientClose");
for(i=0;(i<MAXClient)&&(m_aClientSocket[i]!=wParam);i++) ;
// char chIncomingDataBuffer[10];
// int iBytesRead = recv(m_aClientSocket[i], (LPSTR)(chIncomingDataBuffer), 10, NO_FLAGS);
iErrorCode = closesocket(m_aClientSocket[i]);
m_aClientSocket[i] = INVALID_SOCKET;
if (iErrorCode == SOCKET_ERROR)
ReportWinsockErr("Error closing client socket!");
else
PrintString("==>>客户端套接字成功关闭, 等待下一个客户到达!\n\n");
// PrintString(chIncomingDataBuffer);
return 0L;
}
LRESULT CServerView::OnClientReadClose(WPARAM wParam, LPARAM lParam)
{
switch (WSAGETSELECTEVENT(lParam))
{
case FD_READ:
OnClientRead(wParam,lParam);
break;
case FD_CLOSE:
OnClientClose(wParam,lParam);
break;
}
return 0L;
}
void CServerView::OnUpdateServerOpen(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bServerIsOpen ? FALSE:TRUE);
}
void CServerView::OnUpdateServerClose(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(m_bServerIsOpen ? TRUE : FALSE);
}
LRESULT CServerView::OnServerBroadcast(char acSendBuff[])
{
int i;
for(i=0;i<MAXClient;i++)
{
if(m_aClientSocket[i]!=INVALID_SOCKET)
int iErrorCode = send( m_aClientSocket[i], acSendBuff, lstrlen(acSendBuff), NO_FLAGS);
}
return 0L;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -