热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

多任务处理:服务器协议

服务器协议既然我们将要介绍的多任务服务器方法与特定的客户端-服务器协议相互独立,我们希望能够实现一个同时满足两者的协议。EchoProtocol中给出了回显协议的代码。这个类的静态方法h

服务器协议

 既然我们将要介绍的多任务服务器方法与特定的客户端-服务器协议相互独立,我们希望能够实现一个同时满足两者的协议。EchoProtocol中给出了回显协议的代码。这个类的静态方法handleEchoClient()中封装了对每个客户端的处理过程。除添加了写日志功能(马上会对其介绍)外,这段代码与TCPEchoServer.java中的连接处理部分几乎完全一致。该方法的参数是客户端Socket实例和Logger实例的引用。

 EchoProtocol类实现了Runnable接口(run()方法只是根据该实例的SocketLogger用,简单地调用handleEchoClient()方法),因此我们可以创建一个独立执行run()方法的线程。另外,服务器端的协议执行过程可以通过直接调用这个静态方法实现(为其传入SocketLogger实例的引用)。

 EchoProtocol.java

0 import java.io.IOException;

1 import java.io.InputStream;

2 import java.io.OutputStream;

3 import java.net.Socket;

4 import java.util.logging.Level;

5 import java.util.logging.Logger;

6

7 public class EchoProtocol implements Runnable {

8 private static final int BUFSIZE = 32; // Size (in bytes) of I/O buffer

9 private Socket clntSock; // Socket connect to client

10 private Logger logger; // Server logger

11

12 public EchoProtocol(Socket clntSock, Logger logger) {

13 this.clntSock = clntSock;

14 this.logger = logger;

15 }

16

17 public static void handleEchoClient(Socket clntSock, Logger logger) {

18 try {

19 // Get the input and output I/O streams from socket

20 InputStream in = clntSock.getInputStream();

21 OutputStream out = clntSock.getOutputStream();

22

23 int recvMsgSize; // Size of received message

24 int totalBytesEchoed = 0; // Bytes received from client

25 byte[] echoBuffer = new byte[BUFSIZE]; // Receive Buffer

26 // Receive until client closes connection, indicated by -1

27 while ((recvMsgSize = in.read(echoBuffer)) != -1) {

28 out.write(echoBuffer, 0, recvMsgSize);

29 totalBytesEchoed += recvMsgSize;

30 }

31

32 logger.info("Client " + clntSock.getRemoteSocketAddress() + ", echoed "

33 + totalBytesEchoed + " bytes.");

34

35 } catch (IOException ex) {

36 logger.log(Level.WARNING, "Exception in echo protocol", ex);

37 } finally {

38 try {

39 clntSock.close();

40 } catch (IOException e) {

41 }

42 }

43 }

44

45 public void run() {

46 handleEchoClient(clntSock, logger);

47 }

48 }

EchoProtocol.java

1.声明实现Runnable接口:第7 

2.类成员变量和构造函数:第8-15

每个EchoProtocol实例都包含了一个相应连接的套接字和对logger实例的引用。

3.handleEchoClient():第17-43

实现回显协议:

从套接字中获取输入/输出流:第20-21

接收和回显:第25-30

循环执行直到连接关闭(由read()方法返回值为-1指示),每次循环中在接收到数据后

就立即写回。

在日志中记录连续的详细信息:第32-33

同时记录远端的SocketAddress和回显的字节数。

异常处理:第36

将异常写入日志。

你的服务器每分钟将执行上千次客户端请求。现在有用户报告了一个问题。那么如何才能确定到底发生了什么呢?是不是服务器的问题呢?也许是客户端在破坏这个协议。为了处理这种情况,大部分的服务器都将它们的活动记录写入日志。这里我们只对写日志作非常基础的介绍,不过,你得知道还存在更多的日志记录功能以满足企业级需求。

 首先我们介绍Logger类,它代表了本地或远端的一个日志记录工具。通过该类的一个实例,我们就可以记录服务器的各种活动信息,就像在EchoProtocol中演示的那样。或许你会在服务器上使用多个日志记录器(logger),每个记录器以不同的方式负责不同的需求。例如,你可以有不同的日志记录器分别负责记录操作、安全和出错消息。在Java中,每个日志记录器由一个全局唯一的名字识别。按照如下代码调用Logger.getLogger()静态工厂方法即可获取一个Logger实例:

Logger logger = Logger.getLogger("practical"); 

这行代码用于获取名字为"practical"的记录器。如果这个名字的记录器不存在,则用这个名字创建一个新的记录器,否则,返回已存在的记录器实例。无论在程序中获取名字为"practical"的记录器多少次,都将返回同一个实例。

 有了日志记录器,需要记录什么内容呢?这取决于你要做什么。如果服务器在正常地运行,你可能不想将服务器执行的每一步都记录到日志中,因为记录日志是要消耗系统资源的,如为日志项分配存储空间,写日志需要占用服务器的处理时间等。另一方面,如果是为了调试,你可能就希望记录服务器执行的每一步。为了对不同情况进行处理,记录器中通常包含了日志项的等级或严格度的概念。Level类中就封装了消息的重要程度信息。每个Logger实例都有一个当前等级,每条日志消息也有对应的等级,低于Logger实例的当前等级的消息将被抛弃(即不写入日志)。每个等级都有一个对应的整数值,因此等级之间可以相互比较和排序。系统识别的Level实例共有7种,同时还能创建用户定义的等级,不过通常没有必要这样做。内置的等级(定义为Level类的静态字段)包括:severewarninginfoconfigfinefiner,和finest

 当你写日志的时候,消息又去哪儿呢?记录器将消息发送到一个或多个Handler实例中,该实例用来发布这些消息。默认情况,每个logger有一个ConsoleHandler用来将消息打印System.err中。你也可以为一个logger改变或添加handler(如FileHandler)。注意,与logger一样,每个handler也有自己的最小日志等级,因此要发布一条消息,它的等级必须同时高于loggerhandler的等级阈值。loggerhandler的可配置性很高,包括他们的最小等级。

 Logger对我们来说一个重要的特征是它是线程安全的(thread-safe),即可以在并行运行的不同线程中调用它的方法,而不需要在调用者中添加额外的同步措施。如果没有这个特征,由不同线程记录的不同消息将错乱无章地写到日志中。 

Logger: 查找/创建

static Logger getLogger(String name)

static Logger getLogger(String name, String

resourceBundleName) 

这些静态工厂方法返回指定名字的Logger实例,必要时创建新的实例。

 一旦有了logger,我就需要做的就是……写日志。Logger提供了从细粒度到粗粒度的日志记录工具,并能够区分消息的不同等级甚至消息的上下文。 

Logger: 记录日志消息

void severe(String msg)

void warning(String msg)

void info(String msg)

void config(String msg)

void fine(String msg)

void finer(String msg)

void finest(String msg)

void entering(String sourceClass, String sourceMethod)

void entering(String sourceClass, String sourceMethod,

Object param)

void entering(String sourceClass, String sourceMethod,

Object[] params)

void exiting(String sourceClass, String sourceMethod)

void exiting(String sourceClass, String sourceMethod, 

Object result)

void throwing(String sourceClass, String sourceMethod,

Throwable thrown)

void log(Level level, String msg)

void log(Level level, String msg, Throwable thrown)

severe()warning()等方法根据其名字对应等级,将给定的符合等级的消息写入日志。entering()exiting()方法在程序进入或退出给定类的指定方法时将记录写入日志。注意你也可以选择性地指定额外信息,如参数和返回值等。throwing()方法用于将指定方法所抛出的异常信息写入日志。log()方法提供了一种一般性的日志记录方式,该方法可以指定需要记录的消息等级和内容,并可以选择性地添加异常信息。当然还存在很多其他记录日志的方法,这里我们只提到了主要的几种。 我们可能希望能够通过设置最小记录等级或日志消息处理器的等级,来定制自己的记录器。

 Logger: 设置/获取日志的等级和处理器

Handler[] getHandlers()

void addHandler(Handler handler)

void removeHandler(Handler handler)

Level getLevel()

void setLevel(Level newLevel)

boolean isLoggable(Level level)

getHandlers()方法返回一个包含了和该记录器关联的所有日志处理器数组。addHandler()removeHandler()方法用于给该记录器添加或删除日志处理器。getLevel()setLevel()方法用于获取和设置日志记录的最小等级。isLoggable()方法则在该记录器能够记录所给定的等级的日志时返回true 

现在我们准备介绍一些不同的方法来实现并行服务器。

 

相关下载:

Java_TCPIP_Socket编程(doc)

http://download.csdn.net/detail/undoner/4940239

 

文献来源:

UNDONER(小杰博客) :http://blog.csdn.net/undoner

LSOFT.CN(琅软中国) :http://www.lsoft.cn

 


推荐阅读
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
author-avatar
tuir
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有