`
王者无敌Java
  • 浏览: 69524 次
  • 性别: Icon_minigender_1
  • 来自: 盐城->长沙->深圳
社区版块
存档分类
最新评论

网络通信基础第二式——创建循环等待的多线程服务器

阅读更多
        想必你已经浏览过我的前一篇博文《网络通信基础第一式——创建简单服务器》,并发现了这个简单的服务器的诸多bug。例如:其中有一个极大的缺陷,当一个客户机连接上来后,收到服务器发出的一条消息,按照程序的执行顺序,服务器程序就退出了,如此不稳定的服务器如何让用户信任?当这个问题解决之后,你又会发现新的问题,当用两个telnet客户端连接服务器时,只有一个可以通信,前一个退出后,后一个才能通信,这个也是很致命的问题。一个服务器怎么只能让一个客户机接入呢?实在是太浪费了。。。
        下面,我们就一一解决上诉问题。
        首先,我们先解决服务器不稳定的问题。通过将ServerSocket的accep()在一个循环中调用,实现服务器的循环等待。即当一个客户机通信完毕后,服务器就在此进入循环中,重新调用accep()方法等待下一个客户机的接入,代码示例如下:

			while (true) {
				// 当有客户机连接进来时,返回一个连接对象
				java.net.Socket client = server.accept();// 阻塞,等待客户机连结进入
				System.out.println("有一个客户机访问!");
				// 从连结对象上取得输入输出流
				java.io.InputStream ins = client.getInputStream();
				ous = client.getOutputStream();
				String msg = "Hello!\r\n";
				ous.write(msg.getBytes());
				String input = readString(ins);
				while (!input.equals("bye")) {
					this.jtre.append(input + "\r\n");
					System.out.println("服务器收到的消息是:" + input);
					input = readString(ins);
				}
				msg = "再见!\r\n";
				ous.write(msg.getBytes());
				// 关闭连结
				client.close();
				System.out.println("一个客户机断开了!");
			}

注:如果你要控制服务器的启动和停止,硬编码while的条件为true可不是个好主意,后面会慢慢完善!
        随后,我们将要解决下一个问题,即让多个客户机接入服务器。我们将进入服务器的每一个连接对象(Socket)交由一个线程对象去处理,随后而来的其他连接就不用再等待了。将服务器改造为多线程服务器模型,示意图如下:
代码示例如下:
/**
 * 服务器端处理与客户机连接对象的线程类封装
 * @author king
 *
 */
public class ServerThread extends Thread {

	private java.net.Socket client;// 线程对象要处理的连接变量
	// 创建输入输出流对象
	private InputStream ins;
	private OutputStream ous;

	public ServerThread(java.net.Socket client) {
		this.client = client;
	}

	public void run() {
		processChat(client);
	}

	/**
	 * 处理客户端套接字对象:读取客户机发来的消息,并回显给客户机
	 * 
	 * @param client
	 *            :与客户机连接的套接字对象
	 * @throws Exception
	 */
	public void processChat(java.net.Socket client) {
		
		try {
			//从连接对象上得到输入/输出流对象
			ins = client.getInputStream();
			ous = client.getOutputStream();
			// 服务器发送消息给客户机
			String msg = "您好!我是服务器king。。。\r\n";
			sendMsg(msg);
			// 调用读取字符串的方法,从输入流中读取一个字符
			String input = readString(ins);
			while (!input.equals("bye")) {
				System.out.println("客户机说:" + input);
				msg = "服务器收到的是:" + input + "\r\n";
				System.out.println(msg);
				sendMsg(msg);
				input = readString(ins);// 读取客户机的下一次输入
			}
			msg = "再见,欢迎下次再来!\r\n";
			ous.write(msg.getBytes());
			// 关闭连结
			client.close();
			System.out.println("一个客户机断开了!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void sendMsg(String msg) throws Exception {
		byte[] data = msg.getBytes();
		ous.write(data);// 用输出对象发送
		ous.flush();// 强制输出
	}

	/**
	 * 服务器从输入流中读取字节,并拼成字符串返回 如果读到字节是13,服务器认为以前的一段字节为一个字符串
	 * 
	 * @param ins
	 *            :服务器的输入流的对象
	 * @throws Exception
	 * @return:服务器从输入流(客户机发来的)读到的字符串
	 */
	public String readString(java.io.InputStream ins) throws Exception {

		// 创建一个字符串的缓冲区
		StringBuffer stb = new StringBuffer();
		// 客户机向服务器发送消息
		int i = 0;
		while (i != 13) {// 读到一个回车,就是一句话
			i = ins.read();// 读取客户机发来的下一个字节
			stb.append((char) i);// 把字节转化为字符,并加到缓冲区内
		}
		String s = stb.toString().trim();// 将字节组(缓存区内的)转化为字符串
		s = s.trim();// 调用trim去掉尾部的空格
		return s;

	}
}

        现在的服务器已经可以同时处理多个客户机的连接请求啦,可以说已经完成了一个服务器的雏形,后面就是不断地完善过程啦!敬请期待。。。
  • 大小: 68.6 KB
3
1
分享到:
评论
2 楼 王者无敌Java 2011-01-18  
线程池
HelloJimmy 写道
我猜下一步是实现一个线程池 = =
文章不错

谢谢夸奖!
1 楼 HelloJimmy 2011-01-18  
我猜下一步是实现一个线程池 = =
文章不错

相关推荐

    C#全能速查宝典

    第2章 Windows窗体及常用控件 126 2.1 Form窗体 126 2.1.1 AcceptButton属性——设置接受按钮 126 2.1.2 Activate事件——当激活窗体时发生 126 2.1.3 Appllication类——提供管理应用程序的静态方法 126 2.1.4 ...

    Linux高性能服务器编程

    第二部分对高性能服务器编程的核心要素进行了全面深入的剖析,包含Linux网络编程API、高级I/O函数、Linux服务器程序规范、高性能服务器程序框架、I/O复用、信号、定时器、高性能I/O框架库Libevent、多进程编程、多...

    Java典型模块

    第1篇 Java开发必备基础 第1章 搭建Java开发环境 1.1 Java的过去、现在和未来 1.1.1 Java的历史 ...第31章 俄罗斯方块游戏网络版(Swing+多线程+网络编程) 31.1 俄罗斯方块游戏项目原理 31.1.1 基本原理 ...

    Linux C程序设计大全

    第1篇 Linux下C语言基础 第1章 Linux简介 1.1 GNU简介 1.2 Linux简介 1.2.1 Linux发展史 ...第26章 网络编程实例——简单的Web服务器 第6篇 shell脚本知识 第27章 shell脚本基础 第28章 shell脚本中的控制结构 844

    Visual C++_Turbo C 串口通信编程实践.(电子工业.龚建伟.熊光明) 第二版 电子版

    第2章 多线程串口编程工具CSerialPort类 16 2.1 CSerialPort类的功能及成员函数介绍 16 2.2 应用CSerialPort类编制基于对话框的应用程序 30 2.3 应用CSerialPort类编制基于单文档的应用程序 35 2.4 对CSerialPort...

    Java开发技术大全 电子版

    第2章Java语言基础19 2.1Java语言的特点19 2.2Java程序的构成21 2.3数据类 型23 2.3.1基本数据类型23 2.3.2常量25 2.3.3变量26 2.3.4整型数据27 .2.3.5浮点型数据29 2.3.6字符型数据30 2.3.7布尔型数据32 ...

    嵌入式Linux程序设计案例与实验教程(配套光盘)第二部分

    第2章 嵌入式Linux系统基础12 2.1 构建嵌入式Linux系统环境12 2.1.1 交叉编译12 2.1.2 交叉编译器12 2.1.3 NFS13 实验2.1 嵌入式Linux开发环境的建立14 2.2 Linux C程序设计17 2.2.1 C程序设计概述17 2.2.2 ...

Global site tag (gtag.js) - Google Analytics