`
王者无敌Java
  • 浏览: 70534 次
  • 性别: 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  
我猜下一步是实现一个线程池 = =
文章不错

相关推荐

    Linux网络编程(四)——多线程实现简单的聊天(linux 服务器端 windows客户端)

    在本篇Linux网络编程系列的第四部分中,我们将探讨如何使用多线程技术来实现一个简单的跨平台聊天应用。这个应用包含一个运行在Linux服务器端的程序和一个运行在Windows客户端的程序。通过多线程,我们可以提高系统...

    快速上手linux网络编程tcp服务器(csdn)————程序.pdf

    1. **创建套接字**:相当于准备碗筷,是建立网络通信的第一步。在Linux中,使用`socket()`函数创建一个套接字描述符,这里指定协议族AF_INET(IPv4)和套接字类型SOCK_STREAM(TCP)。 2. **绑定**:就像勺饭,将套...

    java程序设计教程第五版——国外经典教材

    在第五版中,教材涵盖了Java SE(标准版)的主要内容,包括基础语法、类和对象、接口、继承、封装、异常处理、集合框架、输入/输出流、多线程编程、网络编程以及反射机制等。 1. 基础语法:Java的语法结构与C++相似...

    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 c编程————精华版

    - **线程控制**:介绍多线程编程的基础知识,包括线程的创建、同步和通信机制。 ##### 4. 网络编程 - **套接字编程**:详解TCP/IP协议栈的工作原理,以及如何使用套接字进行网络通信。 - **服务器与客户端编程**:...

    学习笔记——资料

    6. **多线程** - **线程创建**:通过Thread类和Runnable接口两种方式创建线程。 - **线程同步**:掌握synchronized关键字、wait()、notify()、notifyAll()方法,理解线程安全问题和解决策略。 7. **网络编程** -...

    Boost程序库完全开发指南——深入C++“准”标准库高清版

    假设我们正在开发一个多线程的网络服务器,需要处理客户端的连接请求,并为每个客户端分配独立的线程来处理数据。此时可以利用Boost库中的多线程组件: 1. 使用`boost::thread`创建多个工作线程。 2. 通过`boost::...

    Java JDK 6学习笔记——ppt简体版

    10. **多线程**:Java支持多线程编程,可以使用Thread类或Runnable接口创建线程。理解线程同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和ReentrantLock类。 11. **网络编程**...

    Linux高性能服务器编程

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

    计算机网络原理实验报告.pdf

    在本实验报告中,主要涉及了计算机网络原理中的一个核心概念——Web服务器的实现,以及如何使用Java语言创建一个多线程的Web服务器。这个实验旨在让学生深入理解Web服务器的工作机制,以及多线程在处理并发请求中的...

    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

    游戏程序设计教程code——何青

    6. **网络编程**:多人在线游戏需要网络编程技术,Java的Socket编程可以实现客户端和服务器之间的通信。 7. **音频处理**:Java Sound API提供了播放、录制和处理音频的能力,为游戏增添音效和背景音乐。 8. **...

    C#入门经典(上)(附带实例讲解)

    第二个实例——在线实时通讯管理器,可能涉及到网络编程和多线程的概念。C#提供了System.Net命名空间,允许开发者进行网络通信,如TCP/IP套接字编程。同时,多线程使得程序可以在同一时间执行多个任务,这对于实时...

    iOS游戏应用源代码——mcconkiee-EMHint-b15b0aa.zip

    网络通信可能使用URLSession或第三方库如Alamofire来处理服务器交互,实现用户数据的同步或在线对战功能。数据存储可能采用Core Data、SQLite或JSON格式,用于保存游戏进度和用户信息。 此外,为了提高用户体验,源...

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

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

    厉害了,Netty 轻松实现文件上传!(csdn)————程序.pdf

    2. **服务器端设置**:创建 `ServerBootstrap` 并配置两个线程组,`bossGroup` 用于接受新连接,`workerGroup` 处理已建立的连接。接着,我们为每个新通道添加处理器链,这通常包括解码器(如 `ObjectDecoder`)和...

Global site tag (gtag.js) - Google Analytics