⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serverbysocketdlg.cpp

📁 自己编写的SOCKET程序 源码有详尽的注释 可以用来学习C/S程序的编写方法
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 *	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 + -