`
吖龙Sam
  • 浏览: 20886 次
  • 性别: 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网络编程(socket---网上广播).rar_Java 网络_Socket网络编程_java socket _ja

    本教程将深入探讨Java中的Socket编程,特别是如何实现网上广播功能。网上广播允许一个设备向网络上的所有设备发送数据,无需预先知道接收者的具体地址。 首先,让我们了解什么是Socket。Socket在计算机网络中是一种...

    java-socket连接nodejs-socket

    Socket编程是一种基础的网络通信机制,允许两个应用程序通过网络交换数据。 首先,让我们深入了解一下Java中的Socket。在Java中,Socket是`java.net.Socket`类的一个实例,它代表了TCP协议中的一个连接。创建Socket...

    Java Socket学习---单线程阻塞

    在Java编程语言中,Socket是实现网络通信的基本组件。"Java Socket学习---单线程阻塞"这个主题主要探讨了如何使用Java的Socket类进行单线程的阻塞式通信,这种模式通常用于简单的客户端-服务器应用。在这个场景中,...

    Java Socket学习---多线程阻塞

    通过对`EchoServer.java`、`SocketUtils.java`和`EchoClient.java`的分析,我们可以深入理解Java Socket编程以及多线程阻塞模式在实际应用中的实现。这对于开发网络应用程序,尤其是需要处理大量并发连接的服务端...

    Java TCP-IP Socket编程-卡尔弗特.pdf

    本资料“Java TCP-IP Socket编程-卡尔弗特.pdf”旨在深入探讨如何利用Java语言进行TCP/IP套接字编程,构建稳定、高效的数据传输通道。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输协议,而...

    java的Socket编程

    在这个主题中,我们将深入探讨Socket编程的基本概念、主要类和方法以及如何通过示例来应用它们。 首先,TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。而Socket是TCP/IP协议族的一...

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

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

    java3d socket编程

    总的来说,要深入学习Java3D和Socket编程,你需要理解3D图形学的基本原理,熟悉Java的网络编程接口,同时还需要一定的编程实践来磨练技能。通过阅读提供的文档和教程,你可以逐步掌握这两个领域的核心知识。

    三步学会Java_Socket编程

    本篇文章将深入讲解如何通过三步学习Java Socket编程。 **第一步:理解Socket** Socket,又称为“套接字”,是网络通信中的一个抽象概念,它封装了IP地址和端口号,是网络通信链路的句柄。在Java中,Socket和...

    java-socket传输文件-图片-源码

    在Java中,Socket API提供了丰富的类库支持,使得开发人员能够轻松实现网络编程。 - **客户端Socket**:用于发起连接请求,与服务端建立连接。 - **服务端Socket**:用于监听客户端的连接请求,并接收或发送数据。 ...

    Java-Socket编程

    在本文中,我们将深入探讨Java Socket编程的概念、原理以及如何使用它来实现客户端-服务器通信。 首先,我们需要了解Socket的基本概念。Socket可以看作是网络上的一个端点,它允许两个运行在不同机器上的程序通过...

    java socket编程

    在本文中,我们将深入探讨Java Socket编程的关键概念、工作原理以及如何创建服务端和客户端,并讨论如何通过多线程支持多个客户端同时在线。 首先,Socket是网络上的两个进程间通信的端点,它允许数据在网络中双向...

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

    《Java TCP/IP Socket编程》(原书第2版)是一本深入探讨Java中Socket编程的专著,旨在帮助读者理解并掌握如何在Java环境中利用TCP/IP协议进行网络通信。本书不仅详细介绍了Socket的工作原理,还提供了丰富的示例...

    java-socketcan

    这个库允许开发者在Java应用程序中实现低级别的CAN数据帧收发,从而无需深入理解底层操作系统或C/C++编程。CAN总线是一种广泛应用于汽车、工业自动化和其他嵌入式系统中的实时通信网络。 标题"java-socketcan"指的...

    华科-计算机网络实验报告-Java_Socket编程-网络组建实验.docx

    ### 华科-计算机网络实验报告-Java_Socket编程-网络组建实验 #### 实验概述 本实验旨在通过具体的编程实践加深学生对于计算机网络中应用层和传输层的理解,特别是Socket编程的应用及其在网络通信中的作用。实验以...

    Java源码:Socket编程.rar_java socket _java编程_socket java_socket编程 jav

    Java Socket编程是网络编程中的重要组成部分,主要用于实现客户端与服务器之间的通信。在Java中,Socket是基于TCP协议的,提供了一种可靠的、基于字节流的双向通信方式。本资料包含的"Java源码:Socket编程"是一个...

    Java TCPIP Socket编程.pdf

    Java TCPIP Socket编程是Java开发语言在后端服务中实现网络通信的重要技术,它基于Apache等开源库提供了丰富的API来创建高效、可靠的网络连接。本章将深入探讨Socket编程的基本概念和实现方法。 1. 计算机网络、...

    Java socket网络编程的基础示例

    在Java中,我们可以使用`java.net.Socket`类和`java.net.ServerSocket`类来实现TCP Socket编程。`ServerSocket`用于监听客户端的连接请求,`Socket`则代表一个客户端连接。以下是一个简单的TCP服务器端和客户端示例...

    java的socket编程课件~~~

    通过深入学习和实践这个Java的Socket编程课件,开发者将能够熟练掌握如何在Java中创建可靠的网络通信,为开发高性能的网络应用程序奠定坚实基础。无论是初学者还是经验丰富的开发者,都应该对Socket编程有深入的理解...

Global site tag (gtag.js) - Google Analytics