📄 serv1vw.cpp
字号:
// START CUSTOM CODE: Internet Programming
VOID CServerView::ReportWinsockErr(LPSTR lpszErrorMsg)
{
wsprintf(m_chMsgBuffer, "\nWinsock error %d: %s\n\n", WSAGetLastError(), lpszErrorMsg);
PrintString((LPSTR)lpszErrorMsg);
MessageBeep(MB_ICONSTOP);
MessageBox(m_chMsgBuffer, AfxGetAppName(), MB_OK|MB_ICONSTOP);
return;
}
// END MODIFICATIONS: Internet Programming
/////////////////////////////////////////////////////////////////////////////
// CServerView message handlers
// START CUSTOM CODE: Internet Programming
LRESULT CServerView::OnServerAccept(WPARAM wParam, LPARAM lParam)
{
int iErrorCode;
int nLength = sizeof(SOCKADDR);
if (WSAGETSELECTERROR(lParam))
{
ReportWinsockErr("Error detected on entry into OnServerAccept.");
return 0L;
}
if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT)
{
PrintString("Connection has arrived!\n");
m_hClientSocket = accept(m_pDoc->m_hServerSocket, (LPSOCKADDR)&m_sockClientAddr, (LPINT)&nLength);
if (m_hClientSocket == INVALID_SOCKET)
{
ReportWinsockErr("Server socket failed to accept connection.");
return 0L;
}
CString csDottedDecimal = "CONNECTED to ";
csDottedDecimal += inet_ntoa(m_sockClientAddr.sin_addr);
m_pDoc->SetTitle(csDottedDecimal);
csDottedDecimal += "\n";
PrintString(csDottedDecimal);
CString csText = "<Title>Internet Programming</Title>";
csText += "<h1>Internet Programming</H1><p><hr>";
csText += "<H3>Kris Jamsa, Ph.D., and Ken Cope</H3><p>";
csText += "<H5>Published by Jamsa Press, 1995</H5><p><hr>";
LPSTR lpszResponse = csText.GetBuffer(1000);
iErrorCode = send( m_hClientSocket, lpszResponse, lstrlen(lpszResponse), NO_FLAGS);
if (iErrorCode == SOCKET_ERROR)
ReportWinsockErr("Error sending response to client.");
else
PrintString("Response sent!\n");
OnClientClose();
}
return 0L;
}
// END MODIFICATIONS: Internet Programming
void CServerView::OnServerClose()
{
if (m_hClientSocket != INVALID_SOCKET)
{
if (WSAAsyncSelect(m_hClientSocket, m_hWnd, NO_FLAGS, NO_FLAGS))
ReportWinsockErr("WSAAsyncSelect error in OnServerClose.");
closesocket(m_hClientSocket);
m_hClientSocket = INVALID_SOCKET;
}
closesocket(m_pDoc->m_hServerSocket);
m_bServerIsOpen = FALSE;
m_pDoc->SetTitle("CLOSED for BUSINESS");
PrintString("\nServer CLOSED for BUSINESS.\n");
return;
}
LRESULT CServerView::OnClientClose(void)
{
int iErrorCode = closesocket(m_hClientSocket);
m_hClientSocket = INVALID_SOCKET;
if (iErrorCode == SOCKET_ERROR)
ReportWinsockErr("Error closing client socket!");
else
PrintString("Client socket closed successfully, ready for next client!\n\n");
m_pDoc->SetTitle("WAITING for CONNECTION");
return 0L;
}
LRESULT CServerView::OnClientClose(WPARAM wParam, LPARAM lParam)
{
if (WSAGETASYNCERROR(lParam))
ReportWinsockErr("Error detected on entry into OnClientClose");
int iErrorCode = closesocket(m_hClientSocket);
m_hClientSocket = INVALID_SOCKET;
if (iErrorCode == SOCKET_ERROR)
ReportWinsockErr("Error closing client socket!");
else
PrintString("Client socket closed successfully, ready for next client!\n\n");
m_pDoc->SetTitle("WAITING for CONNECTION");
return 0L;
}
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 = "\nSERVER READY on ";
csWinsockID += chLocalInfo;
csWinsockID += " at PORT No. ";
csWinsockID += itoa(m_pDoc->m_nServerPort, chLocalInfo, 10);
csWinsockID += "\n";
csWinsockID += wsaData.szDescription;
csWinsockID += "\n";
PrintString(csWinsockID);
// Setup the Winsock server using the same procedures found in the quick programs.
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);
// Bind the server socket like the data socket in the QFTP programs.
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;
}
// Since the application framework handles all the Windows
// dirty work, use the asynchronous Winsock functions and design
// the server for optimal Windows performance.
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("Server socket initialized -- waiting for connections.\n\n");
m_bServerIsOpen = TRUE;
m_pDoc->SetTitle("WAITING for CONNECTION");
// END MODIFICATIONS: Internet Programming
return;
}
LRESULT CServerView::OnClientRead(WPARAM wParam, LPARAM lParam)
{
// Rather than perform recv's in a loop, let Windows
// and Winsock continue to notify the program as data
// arrives in the buffer. If the program performed recvs
// in a loop, the possibility exists that the program might
// receive FD_READ notifications for data that already retrieved.
if (WSAGETASYNCERROR(lParam))
ReportWinsockErr("Error detected on entry into OnClientRead.");
int iBytesRead;
int iBufferLength;
int iEnd;
int iSpaceRemaining;
char chIncomingDataBuffer[1024];
iBufferLength = iSpaceRemaining = sizeof(chIncomingDataBuffer);
iEnd = 0;
iSpaceRemaining -= iEnd;
iBytesRead = recv(m_hClientSocket, (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);
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);
}
void CServerView::OnUpdateServerClose(CCmdUI* pCmdUI)
{
// If the server is open then let the user close it.
pCmdUI->Enable(m_bServerIsOpen ? TRUE : FALSE);
}
void CServerView::OnUpdateServerOpen(CCmdUI* pCmdUI)
{
// If the server is open don't let the user try to open it again.
pCmdUI->Enable(m_bServerIsOpen ? FALSE : TRUE);
}
void CServerView::OnUpdateFileNew(CCmdUI* pCmdUI)
{
// Always disable the file new option for this class.
pCmdUI->Enable(FALSE);
}
void CServerView::OnUpdateFileOpen(CCmdUI* pCmdUI)
{
// Always disable the file open option for this class.
pCmdUI->Enable(FALSE);
}
void CServerView::OnUpdateFileSave(CCmdUI* pCmdUI)
{
// Always disable the file save option for this class.
pCmdUI->Enable(FALSE);
}
void CServerView::OnUpdateFileSaveAs(CCmdUI* pCmdUI)
{
// Always disable the file save as option for this class.
pCmdUI->Enable(FALSE);
}
// END MODIFICATIONS: Internet Programming
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -