Java网络编程笔记_客户端协议处理框架

客户端协议处理框架

 

本文为《Java网络编程精解》客户端协议处理框架这一章的一些学习笔记。

Java对客户程序的通讯过程进行了抽象,提供了通用的协议处理框架,这个框架的优点在与能够封装Socket与服务器通信的细节,在客户程序中一般只需要访问URL和URLConnection类,就能够完成与服务器的通信,框架的具体实现对客户程序是透明的。

作为协议处理框架的实现程序,通常要实现基于特定协议的URLConenction、URLStreamHandler和ContentHandler类的具体子类,此外还要创建URLStreamHandler和ContentHandler类的工厂类,他们负责创建URLStreamHandler和ContentHandler类的具体子类的实力

框架图:

 

实现协议处理框架

  • EchoURLConnection类:继承自URLConnection类
  • EchoURLStreamHandler类:继承自URLStreamHandler类
  • EchoURLStreamHandlerFactory类:实现了URLStreamHandlerFactory接口
  • EchoContentHandler:继承自ContentHandler类
  • EchoContentHandlerFactory:实现ContentHandlerFactory接口

 

创建EchoURLConnection类

EchoURLConnection类实现了connect(),getContentType(),getInputStream()和getOutputStream()方法。EchoURLConnection类封装了一个Socket,在connect()方法中创建与远程服务器连接的Socket对象

package urlFramwork;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;

/**
 * URLConnection子类,理解为某协议与服务器之间的连接
 * @author xusy
 *
 */
public class EchoURLConnection extends URLConnection {
	private Socket connection;
	public static final int DEFAULT_PORT = 8000;

	protected EchoURLConnection(URL url) {
		super(url);
	}

	/* 
	 * 连接服务器
	 */
	@Override
	public void connect() throws IOException {
		//TODO 创建与服务器之间的连接
		if (!connected) {
			int port = url.getPort();
			if (port < 0 || port > 65535)
				port = DEFAULT_PORT;
			connection = new Socket(url.getHost(), port);
			this.connected = true;
		}
	}
	
	/**
	 * 断开服务器
	 */
	public void disconnect() throws IOException{
		if(connected){
			connection.close();
			this.connected = false;
		}
	}

	/* 
	 * 当与服务器建立起连接后,获得InputStream
	 */
	public synchronized InputStream getInputStream() throws IOException {
		if (!connected)
			connect();
		return connection.getInputStream();
	}

	/* 
	 * * 当与服务器建立起连接后,获得OutputStream
	 */
	public synchronized OutputStream getOutputStream() throws IOException { 
		if (!connected)
			connect();
		return connection.getOutputStream();

	}
	
	public String getContentType(){
		return "text/plain";
	}

}

 

 

 创建EchoURLStreamHandler 类和工厂

EchoURLStreamHandler 协议处理器,主要负责创建与协议相关的URLConnection对象,EchoURLStreamHandler类的openConnection()方法负责创建一个EchoURLConenction对象。URL类的openConnection()方法会调用EchoURLStreamHandler类的openConnection()方法。

package urlFramwork;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

/**
 * 负责创建EchoURLConnection对象,URL类的openConnection()方法会调用EchoURLStreamHandler类的openConnection()方法。
 * @author xusy
 *
 */
public class EchoURLStreamHandler extends URLStreamHandler {
	
	@Override
	protected URLConnection openConnection(URL u) throws IOException {
		return new EchoURLConnection(u);
	}

}

 

EchoURLStreamHandler的工厂类 

 

package urlFramwork;

import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;

/**
 *负责创建 EchoURLStreamHandler的工厂类
 * @author xusy
 *
 */
public class EchoURLStreamHandlerFactory implements URLStreamHandlerFactory {

	@Override
	public URLStreamHandler createURLStreamHandler(String protocol) {
		if (protocol.equals("echo"))
			return new EchoURLStreamHandler();
		return null;
	}

}

 

 



  创建EchoContentHandler类和工厂类

对于服务器发送的数据,客户程序可通过URLConnection类的getInputStream()方法获得输入流,然后读取数据,此外URLConnection类还提供了getContent()方法,

它有两种重载形式:

1)public Object getContent()

2) public Object getContent(Class[] classes)

第一个getContent()方法能把服务器发送的数据转换成一个Java对象。第二个getContent()方法的classes参数制定了转换而成的Java对象的类型,getContent()方法把服务器发送的数据优先转换成classes数组中

第一个元素制定的类型,如果转换失败,则尝试转换为classes数组中第二个元素的类型,依次类推。URLConnection类的getContent()方法会调用ContentHandler类的相应的getContent()方法。

在客户端程序中,可以通过一下方式处理服务器发送的数据

URL url = new URL("www.googel.com");

URLConnection connection = url.openConnection();

Class[] classes = {String.class,InputStream.class};

Object o = connection.getContent(classes);

if(o instanceof String){

System.out.prinltn(0)

}else if(o instanceof InputStream){

InputStream in=(InputStream)o;

//处理输入流...

}else{

System.out.println("无法识别服务器发送的数据");

}

 

package urlFramwork;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ContentHandler;
import java.net.URLConnection;

/**
 * @author xusy
 *
 */
/**
 * @author xusy
 *
 */
public class EchoContentHandler extends ContentHandler {

	/*
	 * 读取服务器发送的一行数据,把它转换为字符串对象
	 */
	@Override
	public Object getContent(URLConnection connection) throws IOException {
		InputStream in = connection.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		return reader.readLine();
	}


	/* 
	 * 根据参数classes,将服务器传输来的数据转换为对象并返回
	 * @see java.net.ContentHandler#getContent(java.net.URLConnection, java.lang.Class[])
	 */
	public Object getContent(URLConnection connection, Class[] classes)
			throws IOException {
		InputStream inputStream = connection.getInputStream();
		for (int i = 0; i < classes.length; i++) {
			if (classes[i] == InputStream.class)
				return inputStream;
			else if (classes[i] == String.class)
				return getContent(connection);
		}
		return null;
	}

}

 

 

 

 在客户端程序中,可通过URLConnection类的静态setContetHandlerFactory()方法来设置EchoContentHandlerFactory:

//设置ContentHandlerFactory

URLConnection.setContentHandlerFactory(new EchoContentHandlerFactory());

URL url = new URL("echo://localhost:8000");

EchoURLConnection connection = (EchoURLConenction)url.openConnection();

...

//读取服务器返回的数据,它被包装为一个字符串对象

String echoMsg = (String)connection.getContent();

package urlFramwork;

import java.net.ContentHandler;
import java.net.ContentHandlerFactory;

public class EchoContentHandlerFactory implements ContentHandlerFactory {

	@Override
	public ContentHandler createContentHandler(String mimetype) {
		if(mimetype.equals("text/plain"))
			return new EchoContentHandler();
		else
			return null;
	}

}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值