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

📄 serverdlg.cpp

📁 能模拟计算机网络的停止等待协议的过程
💻 CPP
字号:
// serverDlg.cpp : implementation file
//

#include "stdafx.h"
#include "server.h"
#include "ConfigDlg.h"
#include "serverDlg.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()

/////////////////////////////////////////////////////////////////////////////
// CServerDlg dialog

CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CServerDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CServerDlg)
	m_sShowText = _T("");
	m_sSerIp = _T("");
	m_sSerPort = _T("4000");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CServerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CServerDlg)
	DDX_Text(pDX, IDC_SHOWTEXT_EDIT, m_sShowText);
	DDX_Text(pDX, IDC_SERVERIP_EDIT, m_sSerIp);
	DDX_Text(pDX, IDC_PORT_EDIT, m_sSerPort);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CServerDlg, CDialog)
	//{{AFX_MSG_MAP(CServerDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_SETSERVER_BUTTON, OnSetserverButton)
	ON_MESSAGE(SER_MESSAGE,OnServerMessage)//消息映射
	ON_BN_CLICKED(IDC_BUTTON1, OnENDButton)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CServerDlg message handlers

BOOL CServerDlg::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
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CServerDlg::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 CServerDlg::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 CServerDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

//设置服务器,建立监听端口和会话端口
void CServerDlg::OnSetserverButton() 
{
	// TODO: Add your control notification handler code here
	WSADATA wsaData;
	CString addstr;       //临时字符串
	int ret;
	char name[255]; 
    CString ip; 
    PHOSTENT hostinfo; 
	unsigned short port;

    //初始化socket
	if (WSAStartup(0x101,&wsaData)!=0) 
	{
		AfxMessageBox("WSAStartup() error!");
		return;
	}
	else
	{
		addstr="WSAStartup sucessful!\n";
        Write_to_ShowText(addstr);
	}

	if(ser_sock!= NULL)
    {
        //如果已经创建了套接字先关闭原来的
		closesocket(ser_sock);
		ser_sock = NULL;
	}

	ser_sock=socket(AF_INET,SOCK_STREAM,0);
    if (ser_sock==INVALID_SOCKET)
	{
		AfxMessageBox("socket() error!");
		return;
	}
	else
	{
		addstr="Socket() sucessful!\n";
        Write_to_ShowText(addstr);
	}

	//注册异步事件
	if(WSAAsyncSelect(ser_sock, m_hWnd, SER_MESSAGE, FD_ACCEPT|FD_READ|FD_CLOSE)>0)
		AfxMessageBox("Error select!\n");

	//获取本机IP地址
    if( gethostname ( name, sizeof(name)) == 0)   //返回标准的本机主机名
   { 
       if((hostinfo = gethostbyname(name)) != NULL) //根据主机名返回主机信息
      { 
        ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list); 
      } 
   } 
   //将ip地址显示给用户

	CEdit *output=NULL;
	
	m_sSerIp=ip;
	GetDlgItem(IDC_SERVERIP_EDIT)->SetWindowText(m_sSerIp);
    output=(CEdit*)GetDlgItem(IDC_SERVERIP_EDIT);

	ser_addr.sin_family=AF_INET;

	GetDlgItem(IDC_PORT_EDIT)->GetWindowText(m_sSerPort);
	port=atoi(m_sSerPort);//字符串转换成整形
	ser_addr.sin_port=htons(port);
	ser_addr.sin_addr.S_un.S_addr=inet_addr(ip);
	

	ret=bind(ser_sock,(sockaddr *)&ser_addr,sizeof(ser_addr));
    if (ret!=0)
	{
		AfxMessageBox("Bind() error!");
		return;
	}	
	else 
	{
		addstr="Bind() sucessful!\n";
        Write_to_ShowText(addstr);
	}	

	ret=listen(ser_sock,5);
	if (ret!=0)
	{
		AfxMessageBox("Listen() error!");
		return;
	}	
	else 
	{
		addstr="Begin listening ...\n";
        Write_to_ShowText(addstr);
	}	
	 //服务器设置完毕	
}

//将要显示的信息写入显示框中
void CServerDlg::Write_to_ShowText(CString adds)
{
	CEdit *output=NULL;

	m_sShowText+=adds;
	m_sShowText+="\r\n";

	GetDlgItem(IDC_SHOWTEXT_EDIT)->SetWindowText(m_sShowText);
    output=(CEdit*)GetDlgItem(IDC_SHOWTEXT_EDIT);
	            //跟踪滚动条的位置
	output->LineScroll(output->GetLineCount ());
	return;
}


//网络事件处理函数
LRESULT CServerDlg::OnServerMessage(WPARAM wParam, LPARAM lParam)
{
	int len,recvnum;
	CString addstr,temp,tempstr;
	Cprotocol Pro_stopwait;
	frame r,s;
	bool check;

	char buff[1500],buff1[1500];
	int j;

	switch(lParam)
	{
	case FD_ACCEPT:
		len=sizeof(cli_addr);
		
	    con_sock=accept(ser_sock,(sockaddr *)&cli_addr,&len);
		
	    if (con_sock==INVALID_SOCKET)
		{
			AfxMessageBox("Accept() error!");
		}
	    else
		{
			//显示客户端的IP和端口信息
			addstr.Format("Connect from %s : %d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
            Write_to_ShowText(addstr);
		}
	
	    if(WSAAsyncSelect(con_sock, m_hWnd, SER_MESSAGE, FD_READ|FD_CLOSE)>0)
		   AfxMessageBox("Error select!\n");
        
		frame_expected=0; //建立会话后初始化接收状态变量
		break;
	case FD_READ:
		
		    recvnum=Pro_stopwait.from_physical_layer(con_sock,r);
            //检查对方是否工作正常
			if(recvnum==-1) 
			{
				
			addstr="the sender has closed! Data recieve will be STOP!";
            Write_to_ShowText(addstr);
		    break;
			}
		    addstr="___________________________";
            Write_to_ShowText(addstr);
		
		   //监听到帧到达
		    addstr="Frame arrival!";
            Write_to_ShowText(addstr);
         
		//检验收到的帧是否正确
		if (r.seq==frame_expected)    //接收到序号正确的数据帧
		{
			check=Pro_stopwait.examine_checksum(r);//检验效验和
			switch(check)
			{
				//经过检查传输有错
			case false:

				//发送一个否认帧
				addstr="Check is false, a NAK will be send!";
                Write_to_ShowText(addstr);
				
				//构造否认帧的格式
				s.kind=nak;
 				s.seq=1-s.seq;
				s.ack=frame_expected;
				s.info.data[0]='\0';//数据域为空
				s.checksum=0;       //效验和设为0
				break;
				//数据正确无误
			case true: 
				addstr=Pro_stopwait.to_network_layer(r.info);//把收到的数据上交到网络层
				
		        sprintf( buff1,"%d%d%s%d\n", r.kind,r.seq,addstr,r.checksum );
                addstr.Format("The frame received is :%s",buff1);
                Write_to_ShowText(addstr);

				if(buff1[0]<16)
	                j = sprintf(buff, "0%x ", buff1[0] );
				else
					j = sprintf(buff, "%x ", buff1[0] );
                for(int k=1;k<strlen(buff1);k++)
				{  
				   if(buff1[k]<16)
		           j+=sprintf(buff+j,"0%x ",buff1[k]);
				   else
				   j+=sprintf(buff+j,"%x ",buff1[k]);
				}
				addstr="数据的十六进制的形式是(0x):";
                Write_to_ShowText(addstr);                                 
                addstr.Format("%s%s","0x",buff);
                Write_to_ShowText(addstr);
				 
				inc(frame_expected);      //更新发送状态变量

				//判断是收到的帧是否是特殊帧,若是则在校验位里放入"111",发送出去
				if ((r.info.data[0]=='1')&&(r.info.data[1]=='1')&&(r.info.data[2]=='\0'))
				{  
				   addstr="收到有特殊标志的帧,发送端将停止发送数据!";
				   Write_to_ShowText(addstr);
			       s.kind=ack;
				   s.seq=1-s.seq;
				   s.ack=frame_expected;
				   s.info.data[0]='\0';//数据域为空
				   s.checksum='111'; 
				}
				else
				{

				   //发送一个确认桢
				   addstr="Receive a frame sucessfully,a ACK will be send!";
				   Write_to_ShowText(addstr);

				   s.kind=ack;
				   s.seq=1-s.seq;
				   s.ack=frame_expected;
				   s.info.data[0]='\0';//数据域为空
				   s.checksum=0;       //效验和设为0
				}
			}//end switch
		}
		else   //收到的数据序号不是接收方所需要的
		{
			//发送一个ack
			addstr="The number of this data is not we want, but we still send a ACK!";
			Write_to_ShowText(addstr);

			s.kind=ack;
			s.seq=1-s.seq;
			s.ack=frame_expected;
			s.info.data[0]='\0';//数据域为空
			s.checksum=0;       //效验和设为0
		}
			           //将数据发送出去
		Pro_stopwait.to_physical_layer(con_sock,s);		
	    
		break;
	
	case FD_CLOSE:
		addstr="The Client has closed!";
        Write_to_ShowText(addstr);
		WSACleanup();
	} //end switch
	return 0;
}
//结束网络事件处理函数

void CServerDlg::OnENDButton() 
{
	// TODO: Add your control notification handler code here
	closesocket(con_sock);
	closesocket(ser_sock);
	CDialog::OnOK();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -