📄 serversocket.cpp
字号:
// ServerSocket.cpp: implementation of the CServerSocket class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "songserver.h"
#include "ServerSocket.h"
#include "MainFrm.h"
#include "songserverView.h"
#include "SonglistView.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*///////////////////////////////////////////////
当有客户连接时,客户将自己的计算机名发到服务器端,
以确定不同的用户登录
收到客户发的计算机名后,若当前在线的客户已达到5个
则向客户发送close,要使客户关闭套接字,稍后再连接。
若当前在线的客户少于五个,则向客户发送ok,表示连接
成功。
连接成功后,向两个VIEW类发ADDUSER消息,以更新用户
信息及用户点歌信息
*////////////////////////////////////////////////
int CServerSocket::m_nClientIndex = 0;
int CServerSocket::m_nClientOnline = 0;
CString CServerSocket::m_strClientname[m_nClientNum] = {""};
SOCKET CServerSocket::m_listenSocket = NULL;
SOCKET CServerSocket::m_clientSocket[m_nClientNum] = {NULL};
CServerSocket::CServerSocket()
{
m_hSocket = NULL;
}
CServerSocket::~CServerSocket()
{
}
void CServerSocket::BeginServer()
{
if( m_hSocket != NULL)
return;
m_hSocket = CreateThread(NULL, NULL, ServerThread, NULL, NULL, NULL);
}
void CServerSocket::StopServer()
{
for(int i = 0; i < m_nClientNum; i++)
{
if(m_clientSocket[i] == NULL)
continue;
closesocket(m_clientSocket[i]);
}
m_nClientOnline = 0;
TerminateThread(m_hSocket, 0);
CloseHandle(m_hSocket);
WSACleanup();
}
DWORD CServerSocket::ServerThread(LPVOID lParam)
{
int ret(0);
WSADATA wsaData;
ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (ret != 0)
{
return 1;
}
m_listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_listenSocket == INVALID_SOCKET)
{
WSACleanup();
return 1;
}
struct sockaddr_in sockaddr;
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(8888);
sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
ret = bind(m_listenSocket,(struct sockaddr *)&sockaddr,sizeof(sockaddr));
if (ret == SOCKET_ERROR)
{
closesocket(m_listenSocket);
WSACleanup();
return 1;
}
ret = listen(m_listenSocket, m_nClientNum);
if(ret == SOCKET_ERROR)
{
closesocket(m_listenSocket);
WSACleanup();
return 1;
}
struct sockaddr_in clientSockaddr;
int addrlen=sizeof(clientSockaddr);
//得到主框架类的指针
CMainFrame* pMainWnd = (CMainFrame*)AfxGetMainWnd();
pMainWnd->m_WndSplitter.SetActivePane(0, 1, pMainWnd);
CSongserverView* pListView = (CSongserverView*)(pMainWnd->GetActiveView());
// CSonglistView TreeView;
while(1)
{
SOCKET clientSocket = INVALID_SOCKET;
clientSocket = accept(m_listenSocket, (struct sockaddr *)&clientSockaddr, &addrlen);
if( clientSocket == INVALID_SOCKET)
{
closesocket(m_listenSocket);
return 1;
}
char rcvbuf[256] = {0};
ret = recv(clientSocket, rcvbuf, sizeof(rcvbuf), 0);
if(ret == SOCKET_ERROR)
{
AfxMessageBox("接收消息出错.");
return 1;
}
rcvbuf[ret] = 0;
if( m_nClientOnline == m_nClientNum )
{
char szmsg[] = "close";
send(clientSocket, szmsg, sizeof(szmsg), 0);
Sleep(100);
closesocket(clientSocket);
continue;
}
char szmsg[] = "ok";
send(clientSocket, szmsg, sizeof(szmsg), 0);
for(int i = 0; i < m_nClientNum; i++)
{
if(m_clientSocket[i] == NULL)
{
m_nClientIndex = i;
break;
}
}
switch(m_nClientIndex)
{
case 0:
CreateThread(NULL, NULL, ClientThread_1, pListView, NULL, NULL);
break;
case 1:
CreateThread(NULL, NULL, ClientThread_2, pListView, NULL, NULL);
break;
case 2:
CreateThread(NULL, NULL, ClientThread_3, pListView, NULL, NULL);
break;
case 3:
CreateThread(NULL, NULL, ClientThread_4, pListView, NULL, NULL);
break;
case 4:
CreateThread(NULL, NULL, ClientThread_5, pListView, NULL, NULL);
break;
}
m_clientSocket[m_nClientIndex] = clientSocket;
++m_nClientOnline;
m_strClientname[m_nClientIndex] = rcvbuf;
// TreeView.OnAddUser(m_nClientIndex, rcvbuf);
if( pListView != NULL )
pListView->SendMessage(WM_ADDUSER, (WPARAM)rcvbuf);
}
return 0;
}
int CServerSocket::GetOnlineClientNum()
{
return m_nClientOnline;
}
CString* CServerSocket::GetClientName()
{
return m_strClientname;
}
DWORD CServerSocket::ClientThread_1(LPVOID lParam)
{
int ret = 0;
char rcvbuf[256] = {""};
while(1)
{
ret = recv(m_clientSocket[0], rcvbuf, sizeof(rcvbuf), 0);
if(ret == SOCKET_ERROR)
{
closesocket(m_clientSocket[0]);
m_clientSocket[0] = NULL;
return 1;
}
rcvbuf[ret] = 0;
if( !SendMsg(0, rcvbuf, lParam) )
return 1;
}
return 0;
}
DWORD CServerSocket::ClientThread_2(LPVOID lParam)
{
int ret = 0;
char rcvbuf[256] = {""};
while(1)
{
ret = recv(m_clientSocket[1], rcvbuf, sizeof(rcvbuf), 0);
if(ret == SOCKET_ERROR)
{
closesocket(m_clientSocket[1]);
m_clientSocket[1] = NULL;
return 1;
}
rcvbuf[ret] = 0;
if( !SendMsg(1, rcvbuf, lParam) )
return 1;
}
return 0;
}
DWORD CServerSocket::ClientThread_3(LPVOID lParam)
{
int ret = 0;
char rcvbuf[256] = {""};
while(1)
{
ret = recv(m_clientSocket[2], rcvbuf, sizeof(rcvbuf), 0);
if(ret == SOCKET_ERROR)
{
closesocket(m_clientSocket[2]);
m_clientSocket[2] = NULL;
return 1;
}
rcvbuf[ret] = 0;
if( !SendMsg(2, rcvbuf, lParam) )
return 1;
}
return 0;
}
DWORD CServerSocket::ClientThread_4(LPVOID lParam)
{
int ret = 0;
char rcvbuf[256] = {""};
while(1)
{
ret = recv(m_clientSocket[3], rcvbuf, sizeof(rcvbuf), 0);
if(ret == SOCKET_ERROR)
{
closesocket(m_clientSocket[3]);
m_clientSocket[3] = NULL;
return 1;
}
rcvbuf[ret] = 0;
if( !SendMsg(3, rcvbuf, lParam) )
return 1;
}
return 0;
}
DWORD CServerSocket::ClientThread_5(LPVOID lParam)
{
int ret = 0;
char rcvbuf[256] = {""};
while(1)
{
ret = recv(m_clientSocket[4], rcvbuf, sizeof(rcvbuf), 0);
if(ret == SOCKET_ERROR)
{
closesocket(m_clientSocket[4]);
m_clientSocket[0] = NULL;
return 1;
}
rcvbuf[ret] = 0;
if( !SendMsg(4, rcvbuf, lParam) )
return 1;
}
return 0;
}
////////////////////////////////////////////////////////////////////
/*函数功能: 判断客户端发来的消息是退出还是重新从数据库得到已点歌曲
//参数说明: nIndex: 客户索引
// szbuf: 从客户端接收到的数据
LoadAgain: 重新从数据库得到已点歌曲
select: 查询已用时间和应交费用
quit: 退出程序
// lParam: CSongserverView的指针 */
BOOL CServerSocket::SendMsg(int nIndex, char* szbuf, LPVOID lParam)
{
CTime time;
time = CTime::GetCurrentTime();
if( !strcmp(szbuf, "LoadAgain") )//登录
{
CSonglistView::SetLoadAgain(nIndex);
}
else if( !strcmp(szbuf, "select") )//查询时间和费用
{
//发送已用时间和应付费用到客户端
CString strmsg("");
CString strtmp;
CString strlen;
strtmp = ((CSongserverView*)lParam)->GetUsedTime(nIndex);
strlen.Format("%d", strtmp.GetLength());
strmsg += strlen;
strmsg += strtmp;
strtmp = ((CSongserverView*)lParam)->GetPayForMoney(nIndex);
strlen.Format("%d", strtmp.GetLength());
strmsg += strlen;
strmsg += strtmp;
send(m_clientSocket[nIndex], strmsg.GetBuffer(0), strmsg.GetLength(), 0);
}
else if( !strcmp(szbuf, "reconnect") )//结帐后再连接服务器
{
CString strmsg;
strmsg.Format("%s房间要求重新记费,\n是否同意?", m_strClientname[nIndex]);
int ret = AfxMessageBox(strmsg, MB_ICONINFORMATION | MB_YESNO);
if( ret == 6 )
send(m_clientSocket[nIndex], "ok", 3, 0);
else
send(m_clientSocket[nIndex], "no", 3, 0);
}
else if( !strcmp(szbuf, "payment") )//结帐
{
char* szonline = "否";
((CSongserverView*)lParam)->SendMessage(WM_ADDUSER, (WPARAM)m_strClientname[nIndex].GetBuffer(0), (LPARAM)szonline);
m_nClientOnline--;
}
else if( !strcmp(szbuf, "quit") )//退出
{
char* szonline = "否";
((CSongserverView*)lParam)->SendMessage(WM_ADDUSER, (WPARAM)m_strClientname[nIndex].GetBuffer(0), (LPARAM)szonline);
m_nClientOnline--;
//发送已用时间和应付费用到客户端
CString strmsg("");
CString strtmp;
CString strlen;
strtmp = ((CSongserverView*)lParam)->GetUsedTime(nIndex);
strlen.Format("%d", strtmp.GetLength());
strmsg += strlen;
strmsg += strtmp;
strtmp = ((CSongserverView*)lParam)->GetPayForMoney(nIndex);
strlen.Format("%d", strtmp.GetLength());
strmsg += strlen;
strmsg += strtmp;
send(m_clientSocket[nIndex], strmsg.GetBuffer(0), strmsg.GetLength(), 0);
closesocket(m_clientSocket[nIndex]);
m_clientSocket[nIndex] = NULL;
}
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -