自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(58)
  • 收藏
  • 关注

原创 5.7 小结

   本章讲述了套接字的非阻塞模式,及其运用该模式开发的远程算数运算程序。套结字的非阻塞模式是指套接字在执行操作时,调用的函数不管操作是否完成都会立即返回的工作模式。在使用非阻塞套接字开发Windows Sockets程序时,需要注意对调用函数的错误返回值进行处理。使用非阻塞套接字开发Windows网络应用程序,存在一定难度。但是,使用这种套结字处理同时建立的多个连接,发送和接收的数据

2008-05-11 14:27:00 1190 1

原创 5.6.3 数据接收线程

  RecvDataThread()函数接收服务器发送的数据结果,并负责通知主线程显示该结果。该函数以客户端连接状态bConnecting变量为while语句循环条件。当套结字缓冲区无数据时,recv()函数立即返回,并返回WSAEWOULDBLOCK错误代码。执行continue语句,继续调用recv()函数接收数据结果。当套结字缓冲区有数据时,recv()函数返回读入数据的长度。在

2008-05-11 14:25:00 1791

原创 5.6.2 数据发送线程

  SendDataThread()函数完成客户端数据发送的功能。该函数外层是一个while循环体。当客户端与服务器处于连接状态时bConnecting为TRUE,该函数处于循环状态。在循环中调用Sleep()函数使该线程睡眠TIMEFOR_THREAD_SLEEP时间。当接收到发送数据的通知后,bSendData为TRUE,调用send()函数将发送缓冲区的数据发送出去。当数据发送完毕后

2008-05-11 14:23:00 1046

原创 5.6.1主线程

主线程包括初始化、连接服务器、创建数据接收和发送线程、输入数据和显示结果,以及退出5个部分。其程序流程图,如图所示。客户端的主线程函数清单如下。InitClient()函数完成初始化全局变量和创建非阻塞套接字。如果InitClient()函数失败,则main()函数退出并返回CLIENT_SETUP_FAIL错误代码。ConnectServer()函数实现接服务器的功能。Cre

2008-05-09 18:08:00 1640

原创 5.6 客户端实现

  客户端的实现包括主线程、数据发送线程和数据接收线程3个部分。

2008-05-09 17:50:00 832

原创 5.5.2 界面设计

1.启动界面客户端启动界面如图所示。当服务器接受客户端的连接请求后,客户端显示成功连接服务器信息。同时,提示用户如何输入算数表达式。2.输入算数表达式客户端规定用户第一次必须输入算数表达。其格式为“数字算数运算符数字=”。第一个数字可以带有正负号,第二个数字不能带有正负号。如图所示,用户输入“123+456=”表达式。如果用户输入不符合要求的表达式,界面提示用户重新输入。 

2008-05-09 17:49:00 961

原创 5.5.1 多线程设计

  客户端设计为多线程工作方式,主线程显示用户的输入和数据的计算结果。子线程接收和发送数据。q      主线程用于所有的界面显示和接收用户的输入。q      建立一个数据发送数据线程。当数据打包后,通知该线程向服务器发送数据。q      建立一个数据接收线程。当该线程接收到服务器发送的数据后,由该线程完成对数据的解包,并通知主线程显示结算结果。q      所有的子线程都

2008-05-09 17:47:00 897

原创 5.5 客户端设计

  客户端的设计包括多线程设计和界面设计。客户端使用两个子线程发送和接收数据。其界面比服务器要复杂。

2008-05-09 17:44:00 814

原创 5.4.4清理资源线程

  清理资源线程用于清理为每个接收的客户端分配的资源。由HelperThread()函数实现。该函数工作于服务器两种状态下。1.服务器正在运行在一个for循环中,将管理客户端连接clientlist链表的节点依次取出,然后调用CClient类的IsExit()函数。如果返回值为TRUE,说明该客户端的连接已经关闭,将该节点从clientlist链表中删除,并释放客户端连接实例占用的内存

2008-05-09 17:43:00 911

原创 5.4.3 客户端类

  客户端CClient类对每个接受的客户端,为其实现接收数据、计算数据和发送计算结果的功能。1.CClient类的声明在该类声明如下成员变量。q        m_socket,接受客户端套接字。该套接字继承了sServer套接字的非阻塞模式属性,作为参数调用recv()和send()函数,实现与客户端的数据发送和接收。q        m_addr,接受客户端的地址。q

2008-05-09 17:38:00 1078

原创 5.4.2接受客户端请求线程

  AcceptThread()实现接受客户端的连接请求。该函数是一个for循环体。当服务器处于运行状态时,bServerRunning变量为TRUE,不断地等待客户端的连接请求。当服务器处于即将退出状态时,bServerRunning变量为假,该线程退出。在for循环体中,使用sServer非阻塞套接字不断调用accept()函数。当没有客户端请求接受时,accept()函数立即返回WS

2008-05-09 17:36:00 1139

原创 5.4.1 主线程

  服务器主线程包括初始化、启动服务、停止服务和退出4个模块。其流程图如图所示。服务器的主线程函数清单如下。q        InitSever()函数完成服务器的初始化。如果初始化服务器失败,则释放申请的资源,并返回SERVER_SETUP_FAIL错误代码。q      由StartService()函数启动服务,创建清理资源线程和接受客户端请求线程。如果启动服务失败,

2008-05-09 17:34:00 1428 1

原创 5.4 服务器实现

  服务器的实现包括主线程、接受客户端请求线程、清理资源线程和客户端4个部分。

2008-05-09 17:32:00 857

原创 5.3.2 界面设计

  服务器的界面设计比较简单,主要是启动和退出界面。启动服务器的启动界面如图所示。当用户输入字母“S”后者“s”后,服务器显示启动成功消息,并显示退出服务器的提示,如图所示。  当用户退出服务器时,输入字母“e”或者“E”,系统提示用户确认是否退出服务器如图所示。当用户确认后,服务器需要延迟几秒钟后关闭,如图所示。   

2008-05-09 17:27:00 1118

原创 5.3.1 多线程设计

  服务器设计以多线程方式工作,以接受多个客户端的算数运算请求。q      建立一个用于接受客户端请求线程,等待客户端的连接。q      为每一个接受的客户端都建立一个接收数据线程和一个发送数据线程。当接收线程收到数据后,先计算算数表达式的结果,然后使用事件通知发送数据线程。发送数据接收到事件后,将计算结果发送数据给客户端。q      建立一个资源清理线程,用于及时对服务器的

2008-05-08 16:41:00 1411

原创 5.3 服务器设计

  服务器同时为多个客户端提供服务,实现算术运算和向客户端发送数据的功能。服务器设计包括多线程设计和界面设计。

2008-05-08 15:59:00 948

原创 5.2.2数据包设计

  在客户端和服务器之间传递的数据有算数表达式和消息两种类型。为了识别数据类型,在发送的数据中增加包头。根据包头中的数据类型字段,判断数据是算数表达式还是消息。数据包格式如图所示。包头由数据类型和数据长度组成,共占4个字节。数据类型1个字节。数据长度2个字节。数据长度是指整个数据包的长度。数据类型和数据长度之间的一个字节为没有使用。客户端发送简单的算术表达式,该表达式规定为“数

2008-05-08 15:58:00 1388

原创 5.2.1 需求分析

  该程序基于C/S模式架构,实现客户端和服务器之间TCP/IP通信,完成远程算数运算。图所示,多个客户端向服务器发送算数表达式,服务器接收到表达式之后,进行运算,然后将计算的结果返回给客户端。客户端实现与服务器的多次远程算数运算请求。如图所示,客户端与服务器成功连接后,多次向服务器发送算数表达式,并接收计算结果。当客户端不再要求服务器为其计算数据时,向服务器发送“Byebye”或

2008-05-08 15:56:00 925

原创 5.2 远程算数运算程序

  本节根据第一节讲述的非阻塞模式套接字知识,实现一个可以同时为多个客户端提供服务的远程算数运算程序。该程序分为服务器和客户端两个部分。客户端向服务器发送算术表达式,服务器接收到表达式后,计算该表达式,并将该结果返回客户端。客户端和服务器都使用非阻塞套接字,调用Windows Socketd API,实现数据的发送和接收。

2008-05-08 15:53:00 1044

原创 5.1.3 非塞模式套接字的优势和不足

  由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDBLOCK错误。所以在任何时候,都应仔细检查返回代码并作好对“失败”的准备。应用程序连续不断地调用这个函数,直到它返回成功指示为止。上面的程序清单中,在While循环体内不断地调用recv()函数,以读入1024个字节的数据。这种做法很浪费系统资源。要完成这样的操作,有人使用MSG_PEEK标志调用recv()函数查看缓冲区

2008-05-08 15:52:00 1879

原创 5.1.2 设置套接字的非阻塞模式

  当使用socket()函数和WSASocket()函数创建套接字时,默认都是阻塞的。在创建套接字之后,通过调用ioctlsocket()函数,将该套接字设置为非阻塞模式。函数的第一个参数是套接字,第二个参数设置为FIONBIO,第三个参数设置为unsigned long类型的非零值。下面代码清单演示了如何用ioctlsocket()函数,设置套接字为非阻塞模式。SOCKET      

2008-05-08 15:51:00 7882

原创 5.1.1 非阻塞模式

  把套接字设置为非阻塞模式,即通知系统内核:在调用Windows Sockets API时,不要让线程睡眠,而应该让函数立即返回。在返回时,该函数返回一个错误代码。图所示,一个非阻塞模式套接字多次调用recv()函数的过程。前三次调用recv()函数时,内核数据还没有准备好。因此,该函数立即返回WSAEWOULDBLOCK错误代码。第四次调用recv()函数时,数据已经准备好,被复制到应用程序的

2008-05-08 15:50:00 1012

原创 5.1 套接字的非阻塞模式

  所有Windows平台都支持套接字以阻塞模式和非阻塞模式的方式工作。本节讲述什么是套接字的非阻塞模式,如何设置套接字的非阻塞模式,以及非阻塞套接字在开发Windows Sockets程序中的不足和优势。

2008-05-08 15:33:00 1403 2

原创 第5章 非阻塞模式开发

  套接字的非阻塞模式是指套接字在执行操作时,调用的函数不管操作是否完成都会立即返回的工作模式。非阻塞套接字在处理同时建立的多个连接,发送和接收的数据量不均,时间不定时,明显具有明显的优势。但这种套接字在使用上存在一定难度。本章讲述套接字的非阻塞模式及其一个远程算数运算套接字程序。

2008-05-08 15:15:00 809

原创 4.7 小结

  本章是开发Windows套接字应用程序的开始。本章重点学习套接字的阻塞模式。套接字的阻塞模式是指套接字在执行操作时,调用的函数在没有完成操作之前,不会立即返回的工作模式。客户端与服务器相互问候程序,为学习者介绍了面向连接套接字的服务器和客户端的工作过程。为降低学习者的学习难度,本章的程序代码较少,但涉及到在开发Windows Sockets应用程序的主要API。使用阻塞模式的套接字

2008-05-05 16:57:00 629

原创 4.6.6 退出

  ExitClient()函数负责客户端退出时的资源清理。该函数实现比较简单。有关代码请看本书光盘。

2008-05-05 16:54:00 649

原创 4.6.5 接收数据

  在向服务器发送问候语之后,客户端调用RecvLine()函数接收服务器的应答。RecvLine()函数的实现与服务器相似,不同的是没有对recv()函数调用失败作立即处理,而是返回FALSE。如果RecvLine()函数返回FALSE,则先调用ShowErrorMsg()函数显示错误信息,然后客户端退出。RecvLine()函数程序清单如下。/* *      读取一行数据

2008-05-05 16:52:00 729

原创 4.6.4 发送数据

  在成功连接服务器之后,客户端调用send()函数向服务器发送“Hello, Server!”问候。如果该函数调用失败,则调用ShowErrorMsg()函数显示调用错误信息,再调用ExitClient()函数,退出客户端。发送数据程序清单如下。strcpy(bufSend, "Hello, Server!/n");retVal = send(sHost, bufSend, st

2008-05-05 16:42:00 496

原创 4.6.3 连接服务器

  在客户端连接服务器之前,没有调用bind()函数绑定套接字。在成功调用connect()函数后,该套接字被标识为绑定。这说明connect()函数可以实现对套接字的隐式绑定。客户端在连接服务器之前需要知道它的地址和端口。该地址和端口对客户端来说应该是已知的。该程序中客户端与服务器运行在同一个主机。服务器的端口是5555,它的地址可以通过调用gethostname()和gethostby

2008-05-05 16:41:00 724

原创 4.6.2 创建套接字

  当socket()函数返回INVALID_SOCKET时,调用ShowErrorMsg()函数显示调用失败的原因。创建套接字程序清单如下。//创建Windows socketsHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if(INVALID_SOCKET == sHost){         ShowErrorMsg

2008-05-05 16:39:00 826

原创 4.6.1 初始化

  客户端的初始化包括全局变量和Windows Sockets动态库的初始化两个部分。1.初始化全局变量客户端是Win32 Console Application程序。在程序中使用了一些全局变量,其中包括:q        bufRecv:读缓冲区。q        bufSend:写缓冲区。q        sHost:套接字。q        bConning:与连

2008-05-05 15:41:00 580

原创 4.6 客户端实现

  客户端首先初始化Windows Socket动态库、创建套接字。然后连接服务器,向其发送数据并接收应答。最后,客户端关闭套接字,退出程序。图4.9为客户端工作流程图。客户端的实现包括初始化、创建套接字、连接服务器、发送数据、接收数据和退出6个部分。

2008-05-05 15:40:00 686

原创 4.5.4 退出

如图所示,客户端正在退出。

2008-05-05 15:39:00 512

原创 4.5.3 接收数据

  如图所示,客户端在向服务器发送问候语之后,接收到服务器的应答“Hello,Client!”。 

2008-05-05 15:38:00 571

原创 4.5.2 连接服务器

如图所示。当客户端成功连接服务器后在,界面显示“Connect successfully!”信息。

2008-05-05 15:37:00 651

原创 4.5.1 启动

  如图所示。客户端启动成功后,在界面显示“Client succeeded!”和“Be ready to connect to server...”信息。

2008-05-05 15:22:00 525

原创 4.5 客户端设计

客户端与服务器相互问候程序的客户端主要实现向服务器发起连接请求,发送问候并接收应答的功能。客户端设计主要指界面设计,包括:启动、连接服务器、接收数据和退出。

2008-05-05 15:20:00 737

原创 4.4.8 退出

  ExitClient()函数实现服务器退出。该函数的参数是退出的代码,指示服务器退出时的运行状态。在服务器退出时,关闭监听套接字和客户端连接套接字,下载Windows Sockets DLL,清理内存空间。服务器退出程序清单如下。/* *      退出 */int     ExitClient(int nExit){         closesocket(s

2008-05-05 15:11:00 635

原创 4.4.7 发送数据

  显示客户端问候语之后,服务器向客户端发送应答。SendLine()函数用于发送数据。         //向客户端发送数据         strcpy(bufSend, "Hello,Client!/n");         if (!SendLine(sClient, bufSend))         {                   return     

2008-05-05 15:09:00 815

原创 4.4.6 接收数据

  recvLine()函数实现接收一行数据的功能。在该函数中定义bLineEnd变量作为一行结束的标志。该变量和bConning变量一起作为While语句循环的条件。将recv()函数的第3个参数设置为1,使得该函数每次仅接收一个字符。通过判断接收的字符是否为/n,来判断是否已经接收了一行数据。当接收字符为/n时,将bLineEnd设置为True。While语句循环结束,该函数返

2008-05-05 14:48:00 906

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除