致百米运动员加油稿:VC++ 6.0下使用Winsock控件的局域网通讯程ss序 - 电脑编程技巧与维护

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 13:58:00
VC++ 6.0下使用Winsock控件的局域网通讯程序  

摘 要 介绍在VISCAL C++ 6.0 环境下,使用Winsock控件进行网络通讯的一种方法。Winsock控件的使用简单,可以方便地应用在使用VC++进行编程的网络通讯程序中。

关键词  Winsock控件  局域网  VC6.0

中图分类号:           文献标识码:          文章编号:

 

引言

    随着计算机技术的发展和网络的不断普及,网络通讯程序的应用越来越普遍,各种软件开发平台也为网络通讯程序的开发提供了不同形式的类和控件。在利用Visual C++ 进行开发时,可以使用Csocket类;在利用Visucal Basic 进行开发时,可以使用Winsock 控件。有关Csocket类在VC中的使用和Winsock 控件在VB中使用,已经有许多文章、资料进行的介绍,这里不再赘述。同时也应注意到,利用VC的CSocket类需要对网络通讯的机制和参数有较深的了解,需要较深的计算机知识。虽然CSocket对Winsock进行了封装,但是它的函数调用仍然比较复杂,使用起来不容易。与此相反,在利用VB编程时,各种控件的使用比较简单,不需要许多的参数。利用VB中的Winsock 控件进行开发比较容易,但VB本身的功能不如VC强大,在进行开发时有时会受到一定程度的限制。在VC中利用Winsock控件的使用难度则介于上述二者之间,只需对少许一些参数做简单设置即可。如果在用VC编制程序时需要进行网络通讯而又不想花费过多的时间,在VC程序中插入Winsock控件是一种合适的方法。利用Winsock控件可以编制一个简单的通讯程序,用于局域网之间的微机通讯。

一、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()得到远程计算机上的数据。

二、使用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);

三、程序演示及结论

将上述程序分别编辑、连接为执行程序,生成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++程序中进行网络通讯的一种简便方法。

参考文献

    1.Visual C++(第四版) 原著David J. Kruglinshi  潘爱民 王国印译   机械工业出版社   1999.1

    2.Visual C++ 6开发使用指南 (美)Kate Gregory 著 前导工作室译  机械工业出版社  1999