[返回]
计算机世界1999年第11期

TCP/IP网络通信程序设计

湖北大学数学与计算机科学学院 党德鹏

  本文介绍了TCP/IP网络应用程序的面向对象设计方法,并给出了用Visual C++4.2中MFC在Windows 95环境下开发的程序实例。


  1.Sockets与Winsock 95

  Winsock 95是在Unix Sockets及Windows Sockets基础上发展起来的。Sockets原是BSD为了Unix支持互联网通信而设计的4.3BSD Unix版本中的API,它采用客户服务器模式的通信机制,使网络客户方和服务器方通过Sockets实现网络之间的联接和数据交换;Windows Sockets描述定义了一个Microsoft Windows 的网络编程界面,它为Windows TCP/IP提供了一个BSD型套接字,除与4.3BSD Unix Sockets完全兼容外,还包括一个扩充文件,通过一组附加的API实现Windows 式(即事件驱动)的编程风格;而Winsock 95则是在Microsoft Windows 95中进行网络应用程序设计的接口。Windows 95在Internet支配域中的TCP/IP协议定义了Winsock 95网络编程规范,溶入了许多新特点。MFC中提供了相应的CSocket类来实现网络通信。

  2.Sockets编程原理

  Sockets同时支持数据流Sockets和数据报Sockets。

  下面是利用Socket进行通信连接的过程框图。其中图1是面向连接的时序图,图2是无连接的时序图。
net30_1.jpg (23557 字节)

  由图可以看出,客户与服务器的关系是不对称的。对于TCPC/S,服务器首先启动,然后在某一时刻启动客户与服务器建立连接。服务器与客户开始都必须调用socket()建立一个套接字socket,然后服务器调用bind()将套接字与一个本地网络地址捆扎在一起,再调用listen()使套接字处于一种被动的准备接收状态,同时规定它的请求队列长度,之后服务器就可以调用accept()来接收客户连接。客户打开套接字之后,便可通过调用connect()和服务器建立连接。连接建立之后,客户和服务器之间就可以通过连接发送和接收数据。最后,待数据传送结束,双方调用closesocket()关闭套接字。对于UDPC/S,客户并不与服务器建立一个连接,而仅仅给服务器发送一张包含服务器地址的数据报。相似地,服务器也不从客户端接收一个连接,只是调用函数recvfrom,等待从客户端来的数据。依照recvfrom返回的协议地址以及数据报,服务器就可以给客户送一个应答。

  3.Winsock 95编程方法

  用Visual C++4.2以MFC在Windows 95中实现网络编程,主要就是利用CSocket类及其如下相关成员函数:

  1.BOOL Create(Uint nSocketPort=0,int nSocketType=SOCK_STREAM,longlEvent= FD_READ|FD_WRITE|FD_OOD|FD_ACCEPT|FD_CONNECT|FD_CLOSE|,LPCTSTR|lpszSocketAddress=NULL
该函数用来建立Socket。
  2.BOOL Bind(Uint nSocketPort,LPCTSTR lpszSocketAddess=NULL)
该函数的作用是将Socket端口与网络地址连接起来。
  3.BOOL Listen(int nConnectionBacklog=5)
该函数的作用是等待Socket请求。
  4.Virtual BOOL Accept(CAsyncSocket &rConnected Socket,Socket,SOCKADDR *lpSock Addr=NULL,int *lpSock AddrLen=NULL)
该函数的作用是取得队列上第一个连接请求并建立一个具有与Socket相同特性的套接字。
  5.BOOL Connect(LPCTSTR lpszHostAddress,Uint nHostPort)
该函数的作用是提出请求。其中,lpszHostAddress和nHostPort为接受请求进程的网络地址和Socket端口号。
  6.virtual void Close()该函数的作用是关闭Socket。

  使用以上类及成员函数,按照以下步骤,就可以设计出合适的通信程序:

  Server:Construct→Creat→Bind→Listen→Accept→Send→Close;

  Client:Constuct→Creat→Connect→Receive→Close。

  4.程序实例

  我们用Visual C++4.2中MFC在Windows 95环境下设计了一个daytime cliont程序,清单如下:      头 文 件HEAD.H 内 容:

    #define IDM_STRAT 200

    #define IDM_EDIT 200

   class Mainwnd:public CFrame Wnd

   {public:Mainwnd();

   afx_msg int OnCreat(LPCREATESTRUCT);

   afx_msg void OnStart(void);

DECLARE_MESSAGE_MAP();

   private:Cstatic CSStatic;

    CEdit LineEdit;

    CButten StartButton;};

   class PengApp:public CWinApp

   {public:BOOL InitInstance();}



源 程 序Client.CPP 清 单:

    #include

    #include

    #include “head.h”

   const int nPort=13;

   PengApp theApp;

   Main Wnd:Main Wnd()

   {if(!Create (NULL,“Communication Program”

,WS_OVERLAPPEDWINDOW,rectDefault)) AfxAbort();}

   int Mainwnd:OnCreate(LPCREATESTRUCT)

   {Rect rect;SetRect( & rect,80,50,160,70);

   Create(“Host Name:”,

WS_CHILD|WS_VISIBLE|SS_LEFT,rect,this);

   SetRect( & rect,60,80,180,100);

   LineEdit.Create(WS_CHILD|WS_VISIBLE|WS_

DLGFRAME|ES_LEFT,rect,this,IDM_EDIT);

   SetRect( &rect,100,120,140,140);

   StartButton,Create

(“start”,WS_CHILD|VS_VISIBLE|BS_PUSHBUTTON,

rect,this,IDM_START);

   return 0;}

   BEGIN_MESSAGE_MAP(Main Wnd,CFrameWnd)

   ON_WM_CREATE()

   ON_BN_CLICKED(IDM_START,OnStart)

   END_MESSAGE_MAP()

   BOOL ControlApp:InitInstance()

   {m_pMainWnd=new Main Wnd();

   m_pMainWnd →ShowWindow (m_nCmdShow);

   m_pMainWnd →UpdateWindow();

   return;}

Void Main Wnd:Onstart(void)

   {CSocket TimeClient;

   if(! AfxSocketInit()) MessageBox

(“WindowsSocket initial failed!”,

“Receive”,MB_ICONSTOP);

   if(! TimeClient.Create()) MessageBox

(“ReceiveSocket create failed”,

“Receive”,MB_I(ON)STOP);

   else TimeClient.connect(strAddr,nPort);

   TimeClient.ReceiveFrom

(csReceiveText,csCounts,LineEdit.GetWinText,nPort);

   MessageBox(TimeClient.csReceiveText);

   TimeClient.Close();}