📄 serverbysocketdlg.cpp
字号:
/*
* Copyleft Abelworkshop.
* 文件名称:ServerBySocketDlg.cpp
* 摘 要:SOCKET服务器端程序,用来守候侦听并为客户端提供服务
* 单 位:信息学院
* 作 者:罗涛,2120060434
* 完成日期:2006年11月23日
*/
#include "stdafx.h"
#include "socket.h"
#include "ServerBySocket.h"
#include "ServerBySocketDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
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)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerBySocketDlg dialog
CServerBySocketDlg::CServerBySocketDlg(CWnd* pParent /*=NULL*/)
: CDialog(CServerBySocketDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CServerBySocketDlg)
m_port = 0;
m_connstat = _T("");
m_curlog = _T("");
m_catlog_txt = _T("");
m_UDP_PORT = UDP_PORT;
m_catlog_udp_txt = _T("");
sCal_expression = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CServerBySocketDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CServerBySocketDlg)
DDX_Control(pDX, IDC_CATLOG_UDP, m_catlog_udp);
DDX_Control(pDX, IDC_CATLOG, m_catlog);
DDX_Control(pDX, IDC_IPlist, m_iplist);
DDX_Text(pDX, IDC_PORT, m_port);
DDV_MinMaxInt(pDX, m_port, 1024, 65535);
DDX_Text(pDX, IDC_CONNSTAT, m_connstat);
DDX_Text(pDX, IDC_LOGSTAT, m_curlog);
DDX_Text(pDX, IDC_CATLOG, m_catlog_txt);
DDX_Text(pDX, IDC_PORT_UDP, m_UDP_PORT);
DDX_Text(pDX, IDC_CATLOG_UDP, m_catlog_udp_txt);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServerBySocketDlg, CDialog)
//{{AFX_MSG_MAP(CServerBySocketDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDCLOSE, OnClose)
ON_BN_CLICKED(IDC_STOPSERV, On_Stopserv)
ON_BN_CLICKED(IDC_STARTSERV, On_Startserv)
ON_BN_CLICKED(IDC_STARTSERV2, OnBindTcpPort)
ON_BN_CLICKED(IDC_STARTSERV_UDP, OnStartservUdp)
ON_MESSAGE(NETWORK_EVENT, OnNetEvent)
ON_MESSAGE(NETWORK_LOG, OnLogDisp)
ON_MESSAGE(NETWORK_LOG_UDP, OnLogDisp_UDP)
ON_BN_CLICKED(IDC_STOPSERV_UDP, OnStopservUdp)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerBySocketDlg message handlers
BOOL CServerBySocketDlg::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
memset(&ClientSock, 0, sizeof(ClientSock));//将连接客户SOCK的结构构体全置0
memset(&ClientSock_U, 0, sizeof(ClientSock_U));//将UDP对端返回结构体全置0
U_port = htons(UDP_PORT);
nSele = 0;
InitNetwork();//初始化网络
while (pHost->h_addr_list[nSele++]) {
m_iplist.AddString(ipTostr(*(ulint*)(pHost->h_addr_list[nSele - 1])));
}
m_iplist.SetCurSel(0);
return TRUE; // return TRUE unless you set the focus to a control
}
void CServerBySocketDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 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 CServerBySocketDlg::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 CServerBySocketDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
BOOL CServerBySocketDlg::InitNetwork()
{
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0){
MessageBox("无法初始化SOCKET!", "SOCKET", MB_OK);
SendMessage(WM_CLOSE);
}
//初始化 Raw Socket
if ((ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR){
MessageBox("建立SOCKET出错!", "SOCKET", MB_OK);
closesocket(ServerSock);
WSACleanup();
SendMessage(WM_CLOSE);
}
closesocket(ServerSock);//在初始化时测试socket是否能正常建立:)若不能就不用干了20061120
//设置IP头操作选项,其FLAG设置为TRUE,亲自对IP进行处理
//if (setsockopt(sockRaw, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR){
// ;//MessageBox("setsockopt IP_HDRINCL error!", "RAWSOCKET", MB_OK);
//}
//获取本机名
if (gethostname((char*)LocalName, sizeof(LocalName)) == SOCKET_ERROR){
MessageBox("无法取得本机名!", "SOCKET", MB_OK);
SendMessage(WM_CLOSE);
}
//获取本地 IP 地址
if ((pHost = gethostbyname((char*)LocalName)) == NULL){
MessageBox("无法取得IP地址!", "SOCKET", MB_OK);
SendMessage(WM_CLOSE);
}
return TRUE;
}
void CServerBySocketDlg::OnClose()
{
// TODO: Add your control notification handler code here
if (ServerSock) closesocket(ServerSock);
if (ServerSock_U) closesocket(ServerSock_U);
WSACleanup();
SendMessage(WM_CLOSE);
}
void CServerBySocketDlg::OnNetEvent(WPARAM wParam, LPARAM lParam)
{
//调用Winsock API函数,得到网络事件类型
int iEvent = WSAGETSELECTEVENT(lParam);
//调用Winsock API函数,得到发生此事件的客户端套接字
SOCKET CurSock = (SOCKET)wParam;
switch(iEvent)
{
case FD_ACCEPT: //Connection or multi-point join operation initiated on socket completed
OnAccept(CurSock);//队列里有连接请求,有客自远方来,不亦乐乎?接受之?又是一顿饭钱:(20061123
break;
case FD_CLOSE: //Connection identified by socket has been closed
OnClose(CurSock);
break;
case FD_READ: //Socket ready for reading
OnReceive(CurSock);
break;
case FD_WRITE: //Socket ready for writing
OnSend(CurSock);
break;
default: break;
}
}
void CServerBySocketDlg::OnClose(SOCKET CurSock)//结束与CurSock相应的客户端的通信,释放资源
{
//结束与服务端的通信,释放相应资源
UpdateData(TRUE);//因为后边要送字符到界面,所以先把界面内容取回变量:)20061122
if (CurSock == ServerSock) {
CloseClientSocket(ClientSock);
closesocket(CurSock);
closesocket(ServerSock_U);
m_connstat = "服务已停止";
UpdateData(FALSE);
SendMessage(NETWORK_LOG, LOG_stop_svr, 5);
SendMessage(NETWORK_LOG_UDP, LOG_stop_svr, 5);
OnResum();
return;
}
ClientSock[FindSockNo(ClientSock, CurSock)].inuse = 0;
closesocket(CurSock);//关闭相应的CurSock
total_conn--;
//MessageBox("TCP连接已断开!");
//closesocket(ServerSock_U);
m_connstat = char(total_conn + 48);
m_connstat += "个活动连接";
UpdateData(FALSE);
SendMessage(NETWORK_LOG, LOG_conn_cls, FindSockNo(ClientSock, CurSock));
//OnResum();
}
void CServerBySocketDlg::OnSend(SOCKET CurSock)//发送网络数据包
{
//在给服务端发数据时做相关预处理
//MessageBox("正在发送!");
//UpdateData(TRUE);//因为后边要送字符到界面,所以先把界面内容取回变量:)20061122
//m_curlog = "发送允许";
//UpdateData(FALSE);
}
void CServerBySocketDlg::OnReceive(SOCKET CurSock)//有网络数据包到达,进行处理
{
//读出网络缓冲区中的数据包
//UpdateData(TRUE);//因为后边要送字符到界面,所以先把界面内容取回变量:)20061122
//m_curlog = "接收允许";
//UpdateData(FALSE);
//MessageBox("正在接收!");
memset(&recvbuff, 0, sizeof(recvbuff));//接收缓冲先清0
if ((CurSock != ServerSock_U) && (CurSock != ServerSock)) {//tcp响应
UINT uLen = recv(CurSock, recvbuff, sizeof(recvbuff), 0);
SendMessage(NETWORK_LOG, LOG_recv_str, FindSockNo(ClientSock, CurSock));
if (!strcmp(recvbuff, getUDP)) {//回送UDP端口
SendMessage(NETWORK_LOG, LOG_reqe_udp, FindSockNo(ClientSock, CurSock));
send(CurSock, (const char*)(&U_port), sizeof(U_port), 0);
SendMessage(NETWORK_LOG, LOG_send_udp, FindSockNo(ClientSock, CurSock));
}
if (!strcmp(recvbuff, getTIME)) {//回送服务器时间
_strtime(timestr);
SendMessage(NETWORK_LOG, LOG_reqe_tim, FindSockNo(ClientSock, CurSock));
send(CurSock, timestr, sizeof(timestr), 0);
SendMessage(NETWORK_LOG, LOG_send_tim, FindSockNo(ClientSock, CurSock));
}
if (!strcmp(recvbuff, cutTCP)) { //断开连接
send(CurSock, okCut, sizeof(okCut), 0);
SendMessage(NETWORK_LOG, LOG_disc_tcp, FindSockNo(ClientSock, CurSock));
SendMessage(NETWORK_LOG, LOG_send_tim, FindSockNo(ClientSock, CurSock));
Sleep(5);
closesocket(CurSock);
}
if (uLen == sizeof(cal_T)) {
if (((cal_T*)recvbuff)->flag == 'c') {
char cNum[BUFFER_SIZE];
sCal_expression.Empty();
itoa(((cal_T*)recvbuff)->on1, cNum, 10);
sCal_expression += cNum;
sCal_expression += ((cal_T*)recvbuff)->op;
itoa(((cal_T*)recvbuff)->on2, cNum, 10);
sCal_expression += cNum;
sCal_expression += "=?";
SendMessage(NETWORK_LOG, LOG_reqe_cal, FindSockNo(ClientSock, CurSock));
cal_T sCal_result;
memcpy(&sCal_result, recvbuff, sizeof(cal_T));
switch (sCal_result.op) {
case '+':
sCal_result.result = sCal_result.on1 + sCal_result.on2;
break;
case '-':
sCal_result.result = sCal_result.on1 - sCal_result.on2;
break;
case '*':
sCal_result.result = sCal_result.on1 * sCal_result.on2;
break;
default:
break;
}
itoa(sCal_result.result, cNum, 10);
sCal_expression += cNum;
SendMessage(NETWORK_LOG, LOG_send_str, FindSockNo(ClientSock, CurSock));
//
send(CurSock, (char*)&sCal_result, sizeof(sCal_result), 0);
//MessageBox("计算请求!");
}
}
}
else if (CurSock == ServerSock_U) {//udp所收,原样回敬20061123
recvfrom(CurSock, recvbuff, sizeof(recvbuff), 0, (LPSOCKADDR)&(ClientSock_U.addr), &(ClientSock_U.addr_len));//收UDP包
//MsgBoxNUMA(ntohs(ClientSock_U.addr.sin_port));
SendMessage(NETWORK_LOG_UDP, LOG_recv_str, LPARAM(recvbuff));
if (!strcmp(recvbuff, getTIME)) {//回送服务器时间
_strtime(timestr);
SendMessage(NETWORK_LOG_UDP, LOG_reqe_tim, FindSockNo(ClientSock, CurSock));//findsockno是发现tcp连接的,怎么能发现这个udp连接呢?百思不得其解Abel.20081203
//问题的原因在于:见.h文件的第37行:因为指针越界产生了这样的问题Abel.20081203
//client_sock ClientSock_U;//其实这里就是元素-->ClientSock[CLNT_MAX_NUM],因为sock放在第一个位置Abel.20081203
//MsgBoxNUMA(FindSockNo(ClientSock, CurSock));
//send(CurSock, timestr, sizeof(timestr), 0);
sendto(CurSock, timestr, sizeof(timestr), 0, (LPSOCKADDR)&(ClientSock_U.addr), ClientSock_U.addr_len);//送回文
SendMessage(NETWORK_LOG_UDP, LOG_send_tim, FindSockNo(ClientSock, CurSock));//findsockno是发现tcp连接的,怎么能发现这个udp连接呢?百思不得其解Abel.20081203
}
//sendto(CurSock, recvbuff, sizeof(recvbuff), 0, (LPSOCKADDR)&(ClientSock_U.addr), ClientSock_U.addr_len);//送回文
//SendMessage(NETWORK_LOG_UDP, LOG_send_str, LPARAM(recvbuff));
}
}
void CServerBySocketDlg::OnAccept(SOCKET CurSock)//处理客户端的连接请求
{
//建立与服务端的的通信,取得UDP端口号
//MessageBox("正在连接!");
/*UpdateData(TRUE);//因为后边要送字符到界面,所以先把界面内容取回变量:)20061122
if (1) {
m_connstat = "连接成功";
}
else {
m_connstat = "连接失败";
}
UpdateData(FALSE);*/
//MessageBox("有人请求连接!");
//if (CurSock == ServerSock) {
// MessageBox("是TCP socke返回的!");
// return;
//}
int temp = 0;
int CurConn = FindFirstEmpty(ClientSock);
if ((CurConn < CLNT_MAX_NUM) && (total_conn <= CLNT_MAX_NUM)) {
ClientSock[CurConn].Sock = 0xFFFFFFFF;
//while (ClientSock[CurConn].Sock == 0xFFFFFFFF) {
ClientSock[CurConn].Sock = accept(ServerSock, (LPSOCKADDR)&(ClientSock[CurConn].addr), &(ClientSock[CurConn].addr_len));
//}
temp = WSAGetLastError();
ClientSock[CurConn].inuse = 1;
total_conn++;//连接总数加一,20061123
if(WSAAsyncSelect(ClientSock[CurConn].Sock, m_hWnd, NETWORK_EVENT, FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR){
MessageBox("注册网络异步事件失败!");
closesocket(ServerSock);
closesocket(ServerSock_U);
OnResum();
return;
}
m_connstat = char(total_conn + 48);
m_connstat += "个活动连接";
UpdateData(FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -