`
吖龙Sam
  • 浏览: 20284 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java中的Socket编程(3)-深入

    博客分类:
  • Java
阅读更多

读不在三更五鼓,功只怕一曝十寒。—郭沫若
意思是说,学习不在某一时的努力,而要锲而不舍的坚持才能成功!
这句话告诉我们,学习是一个循序渐进的积累过程,急于求成是不可取的,而想一劳永逸,想到的时候就用功一时,想不到的时候就疏于学业,这样也只能算是学无所成的。

上一次我们实现了一个服务端和客户端同时读写的程序,但是服务端在处理完一个客户端的请求之后就结束了,而不能继续接收其他客户端的请求,这种方式还不能满足我们实际开发中的需要。今天我们来实现一个更贴近实际情况的程序:

1、需求:一个服务端异步处理多个客户端的请求
核心点:服务端通过accept方法监听客户端请求,当接收到某个客户端请求时,开启一个新的线程来处理请求,然后继续回到监听状态。这样就实现了异步处理客户端请求的程序。

2、代码实现:
1)服务端代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 * 需求:多个客户端连接同一个服务端
 * @author Sam
 *
 */
public class MultipleServer {
	
	/** 编码 */
	public static final String ENCODING = "UTF-8";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		try {
			// 创建一个服务端ServerSocket,监听指定端口的请求
			ServerSocket ss = new ServerSocket(10000);
			System.out.println("Server 等待客户端接入...");
			while (true) {
				// 一直循环监听客户端请求
				Socket socket = ss.accept();
				// 开启一个新线程处理Socket请求
				new Thread(new AsynSocketTask(socket)).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 用于处理Socket请求的任务类
	 *
	 */
	static class AsynSocketTask implements Runnable {
		
		private Socket socket;
		private BufferedReader buffReader;
		private BufferedWriter buffWriter;
		
		public AsynSocketTask(Socket socket) {
			try {
				this.socket = socket;
				// 获取Socket中的输入输出流,并使用带缓冲区的字符流
				buffReader = new BufferedReader(
						new InputStreamReader(socket.getInputStream(), ENCODING));
				buffWriter = new BufferedWriter(
						new OutputStreamWriter(socket.getOutputStream(), ENCODING));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void run() {
			handleSocketRequest();
		}

		/**
		 * 处理客户端请求
		 */
		private void handleSocketRequest() {
			try {
				////////////////  读操作    //////////////////
				// 获取客户端数据
				String line = null;
				StringBuilder sBuilder = new StringBuilder();
				// 一行一行的读
				while ( (line=buffReader.readLine()) != null ) {
					if (line.indexOf("eof") != -1) {// 读到结束标记,则跳出循环
						break;
					}
					sBuilder.append(line);
				}
				System.out.println("Server 来自客户端的数据:"+ sBuilder.toString());
				
				////////////////  写操作    //////////////////
				// 读完之后,往客户端写一句
				buffWriter.write("Hello Client!");
				buffWriter.newLine();// 写一个换行符
				buffWriter.write("eof");// 写一个结束标记符
				buffWriter.newLine();
				
				buffWriter.close();// 关闭该流的同时,也会释放与之关联的所有资源
				buffReader.close();
				socket.close();
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}


服务端代码分析:
1、在主程序中,我们使用了一个while(true)死循环,监听客户端请求,当监听到有请求过来,就开启一个新线程来处理,然后主程序回到原来的监听状态。实际开发中也是这种情况的,服务端应该一直处于开启状态,可以随时响应客户端请求。
2、为了避免出现乱码,服务端和客户端读写数据统一使用UTF-8编码格式。
3、为了提高读写效率,程序中我们使用了带缓存区的字符输入输出流,一行一行的读写数据;其中readLine方法是阻塞式操作的,只有读到一个换行、回车或换行回车符时才会执行往后的操作,否则一直处于阻塞状态。而newLine方法是往流中写一个换行符。

2)客户端代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * 客户端
 * @author Sam
 *
 */
public class MultipleClient {
	
	/** 编码 */
	public static final String ENCODING = "UTF-8";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			// 与服务端建立连接(服务端主机号,服务端监听的端口号)
			Socket socket = new Socket("127.0.0.1" , 10000);
			// 获取Socket中的输入输出流,并使用带缓冲区的字符流
			BufferedWriter buffWriter = new BufferedWriter(
					new OutputStreamWriter(socket.getOutputStream(), ENCODING));
			BufferedReader buffReader = new BufferedReader(
					new InputStreamReader(socket.getInputStream(), ENCODING));
			
			///////////////  写操作    ///////////////
			// 往服务端写数据
			buffWriter.write("Hello Server!");
			buffWriter.newLine();// 写一个换行符
			buffWriter.write("eof");// 写一个结束标记符
			buffWriter.newLine();
			buffWriter.flush();
			
			///////////////  读操作    ///////////////
			// 写完之后,读取服务端返回的数据
			socket.setSoTimeout(10*1000);// 设置超时时长10秒
			String line = null;
			StringBuilder sBuilder = new StringBuilder();
			// 一行一行的读
			while ( (line=buffReader.readLine()) != null ) {
				if (line.indexOf("eof") != -1) {// 读到结束标记,则跳出循环
					break;
				}
				sBuilder.append(line);
			}
			
			buffWriter.close();
			buffReader.close();
			socket.close();
			
			System.out.println("Client 来自服务端的数据:" + sBuilder.toString());
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}


客户端代码分析:
1、这里的代码逻辑,跟前两篇文章中的代码是一样的,只是有个需要注意的方法:setSoTimeout(int timeout)
设置超时时长,单位是毫秒。当设置了超时时长大于0时,表示Socket在这一时间内,如果没读取到数据,则不会一直阻塞在那里,而是抛出一个SocketTimeoutException异常。

3、运行结果:
注意:先运行Server程序,再运行Client程序。为体现服务端可以处理多个客户端请求,把Client程序拷贝到硬盘的某个路径,编辑文件,修改往服务端写数据的内容,然后在dos控制台再运行一次。即


结果如下:
1)Server程序控制台:


2)Client程序控制台:


3)dos命令控制台:


4、总结:
经过前面两章和本章的学习,我相信大家对Socket会有了一个更深入的了解,前面两章的内容均是为了本章内容而做铺垫的,实际开发中,就是使用本章这种方式,一个服务端异步响应多个客户端请求。以后更复杂的程序也是在这基础上拓展的,要学会融会贯通,以不变应万变。
  • 大小: 22.5 KB
  • 大小: 9 KB
  • 大小: 26.8 KB
  • 大小: 68.8 KB
分享到:
评论

相关推荐

    Java TCP IP Socket编程(原书第2版).

    《Java TCP/IP Socket编程(原书第2版)》基于TCP/IP Socket相关原理,对如何在Java中进行Socket编程作了深入浅出的介绍。《Java TCP/IP Socket编程(原书第2版)》内容简明扼要,条理清晰,并在讲解相应的概念或编程...

    Java TCP/IP Socket编程

    《Java TCP/IP Socket编程(原书第2版)》基于TCP/IP Socket相关原理,对如何在Java中进行Socket编程作了深入浅出的介绍。《Java TCP/IP Socket编程(原书第2版)》内容简明扼要,条理清晰,并在讲解相应的概念或编程...

    (超赞)JAVA精华之--深入JAVA API

    1.8 Java Socket编程 1.9 Java的内存泄漏 1.10 抽象类与接口的区别 1.11 Java变量类型间的相互转换 2 JAVA与WEB 2.1 JMX规范 2.1.1 JMX概述 2.1.2 设备层(Instrumentation Level) 2.1.3 代理层 2.1.4 分布服务层 ...

    深入Java Servlet网络编程

    第5章 Java Servlet中的网络编程 5. 1 Java套接字网络编程 5. 1. 1 InetAddress类 5. 1. 2 Socket类 5. 1. 3 给手机发送网上短信息 5. 2 Java网络编程中的高层类 5. 2. 1 URL类 5. 2. 2 URLConnection类 第6...

    Java Socket编程

    使用 JAVA 进行Socket编程,该书深入讨论了Socket编程及其在网络通信,多任务处理中的应用。

    java网络编程socket非阻塞通信

    通过java网络编程深入理解socket阻塞通信和非阻塞通信的在网络中的应用 源码包每一行都有注释,在代码里面每一个类都有详细的注释来解释这个类的功能这个方法的功能,调用哪一个类的哪一个功能等等。 压缩包包含实验...

    Java CP/IP Socket编程

    JAVA SOCKET 编程的经典之书,(中文版)里面的代码可直接复制使用! 目录: 第1章简介..........3 1.1 计算机网络,分组报文和协议..........3 1.2 关于地址..........6 1.3 关于名字..........8 1.4 客户端...

    java应用与开发 Java实验,综合应用 运用Java语言的各方面知识解决实际问题,提高综合编程能力

    用途: 学习Java中的类的概念和使用,深入理解面向对象编程。 实验三: 关键词: 异常处理机制与数据流 内容关键词: 异常处理,数据流,Java实验 用途: 掌握Java中的异常处理机制和数据流操作,提高代码的稳定性和可靠...

    java socket

    深入阐述了java socket编程技术

    蚂蚁课堂(每特学院)第一期-Java高端培训视频教程

    0007--Java网络编程之socket.zip ├─0008--Maven.zip ├─0009--Web开发入门.zip ├─0010--深入理解Servlet.zip ├─0011--Session与Cokile实现原理.zip ├─0012--深入理解Http协议.zip ├─0013--Mybatis.zip ├...

    《Java程序设计实训》报告 多人聊天室

    4、使用网络编程,掌握基于TCP协议的Socket编程,了解Socket编程的协议约定,掌握简单应用协议的开发。  5、使用C/S架构,对网络编程有一定的了解 二.项目概述 运用java程序编写聊天室,实现简单的聊天功能。它是...

    Java超神之路.rar

    3.I/O,Socket编程,首先要熟悉Java中Socket编程,以及I/O包,再深入下去就是JavaNIO,再深入下去是操作系统底层的Socket实现,了解Windows和Linux中是怎么实现socket的,如果你想学习Java可以来这个群,首先是五三二...

    java后端宝典进阶版.zip

    Java网络编程:介绍Java中的网络编程相关知识,包括Socket编程、HTTP协议、TCP/IP等,帮助读者理解和应用网络编程技术。 Java框架和工具:介绍常用的Java开发框架和工具,如Spring、MyBatis、Maven等,帮助读者提高...

    Java毕业设计-JAVA基于局域网的聊天室系统(源代码+论文).rar

    **JAVA基于局域网的聊天室系统** 本资源提供了一套完整的基于Java实现的局域网聊天...通过学习和实践,您可以深入了解Java Socket编程原理,掌握局域网通信的核心技术,并能够根据实际需求对系统进行二次开发和定制。

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    上架时间:2010-3-30 出版日期:2010 年3月 开本:16开 其他详细信息查看:http://www.china-pub.com/196571 编辑推荐 Java编程老鸟潜心写作,奉献高效率的Java学习心得 完全站在没有编程经验读者的角度,...

    java技术书籍合集

    Java TCP_IP Socket编程(2版), 深入理解Java虚拟机(第2版), 机器学习实践指南:案例应用解析(第2版) 非常建议平时多读读前两本书,虽然它们是最短的,确实最有用的,阿里的建议还是很给力的,会少踩很多的坑的...

    Java精华学习资料

    Java精华学习资料 深入JAVA API 深入理解嵌套类和内部类 文件和流 java中的一些常用词汇 J2SE学习中的30个基本概念 ...Java Socket编程 Java的内存泄漏 抽象类与接口的区别 Java变量类型间的相互转换 ……

Global site tag (gtag.js) - Google Analytics