基于WINSOCK控件的VC网络通讯程序

来源:互联网 发布:微信为什么要封淘宝客 编辑:程序博客网 时间:2024/06/06 16:28
利用Winsock控件可以编制一个简单的通讯程序,用于局域网之间的微机通讯。
1 Winsock控件的使用方法
1.1通讯协议的选择
Winsock控件提供了访问 TCP 和 UDP 网络服务的方便途径。采用TCP协议可以提供双向的、可靠的、有序的和无重复投递的数据流。TCP允许创建和维护与远程计算机的连接,连接两台计算机就可彼此进行数据传输。用户数据文报协议 (UDP) 是一个无连接协议。采用UDP协议,支持双向的数据流,但不保证有序、可靠或无重复的投递。但计算机并不建立连接。
在使用中,采用TCP协议的编程模型应用最为广泛,因为面向连接协议提供了一系列的数据纠错功能,可以保证在网络上传输的数据及时、无误地到达对方,Internet上的多数服务(WWW、FTP、Telnet、SMTP)就是靠此协议运转的。采用UDP协议由于不用建立连接,传输比连接协议快,无数据纠错功能,不保证数据的可靠传递。在这里本文只介绍使用TCP/IP协议进行编程的方法。
1.2使用方法和主要函数
    Winsock控件的使用方法和步骤如下图所示。
      
1.2.1 VARIANT类型变量的使用
   Winsock控件使用的一个特殊的数据类型为VARIANT结构,其中vt的值类型说明了它所存储的数据,vt的几个主要的值类型及值域为:
  类型                      值域                说明
vt=VT_BSTR          bstrVal         字符串类型
vt=VT_I2                  Ival                     整数类型
vt=VT_ERROR      scode                  错误代码
在使用之前,应对VARIANT变量的类型和值域进行赋值。一般的使用方法为:
VARIANT [variant name]
[variant name].vt=[variant type]
[variant name].[variant type]=[value]
例如:
   Cstring  m_host;
   m_host="Room312";
   VARIANT  vtHost;
   vtHost.vt=VT_BSTR;
   vtHost.bstrVal=m_host.AllocSysString();
1.      2.2 Server程序使用的主要函数
    Bind()函数指定用于 TCP 连接的 LocalPort 和 LocalIP。
    Listen()函数设置侦听模式。该方法仅适用于 TCP 连接。
    Accept()在处理 ConnectionRequest 事件时用这个方法接受新连接。
    SendData()用于数据的发送。
    Close()关闭与对方的连接。
1.2.3Client程序使用的主要函数
    Connect()要求连接到远程计算机。
    GetData()得到远程计算机上的数据。
2 使用Winsock控件的局域网通讯程序
2.1 Server程序
   利用ClassWizard建立一个ServerDemo程序,注意选择SDI,支持ActiveX,将View类设为CFormView类, 从Project->Add File->Compont and Control, 在对话框中选Registered ActiveX,选择Microsoft WinSock Control ,点击Insert按钮,依照缺省设置即可。这样在工程文件中会出现mswinsockcontrol类编辑ServerDemo程序的主对话框,可以看到在控件面版上出现mswinsockcontrol类的控件。在对话框中加入控件和相应的变量,如表1所示
 
控件
控件ID
变量名
类型
Edit
IDC_EDIT1
 m_edit
CString
按钮
IDC_SEND
 
 
Winsock
IDC_WINSOCK1
 m_server
控制
Winsock
IDC_WINSOCK2
 m_connect
控制
 
(1)在ServerDemoView.h中,加入以下变量
 VARIANT localport;
 VARIANT localip;
 CString strport;
 CString strip;
 VARIANT vtCommand;
 CString m_command;
 VARIANT vtData;
 VARIANT vtType;
 VARIANT vtMaxlen;
(2)在ServerDemoView .cpp的构造函数中加入:
    localport.vt=VT_BSTR;
    localip.vt=VT_BSTR;
    strport="4000";
   strip="128.1.0.139";//在程序中应将“128.1.25.240”设为自己server  
                      //的IP地址
   vtCommand.vt=VT_BSTR;
   m_command="Server Send";
   vtData.vt=VT_BSTR;
   vtType.vt=VT_ERROR; 
(3)利用ClassWizar映射OnInitialUpdate()的响应:在其中加入代码:
   localport.bstrVal=strport.AllocSysString();
   localip.bstrVal=strip.AllocSysString();
   m_server.Bind(localport, localip);
   m_server.Listen();
(4)利用ClassWizar响应IDC_WINSOCK1的ConnectionRequest事件,在OnConnectionRequestWinsock1()中加入代码:
    if(m_connect.GetState()==0 )
       m_connect.Accept(requestID);
    else
    AfxMessageBox("no more connects",MB_OK);
(5)利用ClassWizar映射ID_SEND的动作:OnSend(),在其中加入代码:
    m_edit.GetWindowText(m_command);
    vtCommand.bstrVal=m_command.AllocSysString();
    m_connect.SendData(vtCommand);
(6)利用ClassWizar响应ID_WINSOCK2的DataArrival事件,在OnDataArrivalWinsock2()中加入代码:
    CString m_MBody;
    vtMaxlen.vt=VT_I2;
    vtMaxlen.iVal=bytesTotal;
    vtData.bstrVal=strport.AllocSysString();
    vtType.bstrVal=strport.AllocSysString();
    m_connect.GetData(&vtData,vtType,vtMaxlen);
    m_MBody=vtData.bstrVal;
    m_edit.SetWindowText( m_MBody);
(7)利用ClassWizar响应ID_WINSOCK2的Close()事件,在OnCloseWinsock2()中加入代码:
    m_connect.Close();
(8)在DestroyWindow() 中加入:
    m_server.Close();
    m_connect.Close();
2.2 Client程序
    利用ClassWizard建立一个ClientDemo程序,注意选择SDI,支持ActiveX,将View类设为CFormView类, 从Project->Add File->Compont and Control, 在对话框中选Registered ActiveX,选择Microsoft WinSock Control ,点击Insert按钮,依照缺省设置即可。这样在工程文件中会出现mswinsockcontrol类。编辑ClientDemo程序的主对话框,可以看到在控件面版上出现mswinsockcontrol类的控件。在对话框中加入控件和相应的变量,如表2所示
表2控件表
控件
控件ID
变量名
类型
Edit
IDC_EDIT1
 m_edit
CString
按钮
IDC_CONNECT
 m_connect
控制
按钮
IDC_SEND
 
 
Winsock
IDC_WINSOCK1
 m_socket
控制
 
(1)在ClientDemoView.h中,加入以下变量
   CString m_host;
   CString m_port;
   VARIANT vtHost;
   VARIANT vtPort;
   VARIANT vtData;
   VARIANT vtType;
   VARIANT vtMaxlen;
   VARIANT vtCommand;
   CString m_command; 
(2)在ClientDemo.cpp的构造函数中加入:
   m_host=_T("Room312");//在程序中将“Room312”设为自己server的主机
                        //名
   m_port=_T("4000");   //端口设为4000;
   m_command=_T("Client send");
   vtHost.vt=VT_BSTR;
   vtPort.vt=VT_BSTR;
   vtData.vt=VT_BSTR;
   vtType.vt=VT_ERROR;
   vtCommand.vt=VT_BSTR;
(3)利用ClassWizar映射ID_CONNECT的动作:在OnConnect()中加入代码:
   m_socket.SetRemoteHost("Room312");//在程序中将“Room312”设为自己
                                  //server的主机名
   m_socket.SetRemotePort(4000);
   vtHost.bstrVal=m_host.AllocSysString();//见CString类字符串转化为
 //系统字符串
   vtPort.bstrVal=m_port.AllocSysString();
   m_socket.Connect(vtHost,vtPort);
   if(m_socket.GetState()==0) //如果m_socket已经断开连接,将connect
                            //设置为可用
       m_connect.EnableWindow(true);
   else
      m_connect.EnableWindow(false);
(4)利用ClassWizar映射ID_SEND的动作:在OnSend:
    m_edit.GetWindowText(m_command);
    vtCommand.bstrVal=m_command.AllocSysString();
    m_socket.SendData(vtCommand);
(5)利用ClassWizar响应ID_WINSOCK1的DataArrival事件,在 OnDataArrivalWinsock1(long bytesTotal)中加入代码:
   CString m_MBody;
   vtMaxlen.vt=VT_I2;
   vtMaxlen.iVal=bytesTotal;
   vtData.bstrVal=m_host.AllocSysString();
   vtType.bstrVal=m_port.AllocSysString();
   m_socket.GetData(&vtData,vtType,vtMaxlen);
   m_MBody=vtData.bstrVal;
   m_edit.SetWindowText(m_MBody);
(6)在DestroyWindow()中加入:
    m_socket.Close();
(7)利用ClassWizar响应ID_WINSOCK1的Close事件,在OnCloseWinsock1()中加入代码:
    m_socket.Close();
    if(m_socket.GetState()==0)
      m_connect.EnableWindow(true);
else
      m_connect.EnableWindow(false);
3.程序演示及结论
将上述程序分别编辑、连接为执行程序,生成serverdemo.exe和clientdemo.exe文件。确认程序中主机名和IP地址无误。如果计算机没有连网,可以在程序中使用本机的主机名和IP地址。首先运行serverdemo.exe。它自动进入到监听状态。随后运行clientdemo.exe,点击connect按钮。如果client与server 连接成功,connect按钮变为灰色(不可用)。连接成功后,在编辑框中输入文字,点击send按钮,在serverdemo程序的编辑框中可以看到clientdemo程序发送的文字。同样,在serverdemo的编辑框中输入文字,点击send按钮,在clientdemo程序的编辑框中可以看到serverdemo程序发送的文字。
通过上述程序可以看到,同MFC的Csocket类相比,Winsock控件的使用简单方便。程序中并未涉及Winsock最基本的API函数以及TCP/IP的相关知识,编程简单明了,是在VC++程序中进行网络通讯的一种简便方法。
原创粉丝点击