`

1,用NIO实现阻塞的EchoServer和EchoClient

 
阅读更多

EchoServer采用阻塞模式,用线程池中的工作线程处理每个客户连接。

EchoClient也采用阻塞模式,单线程。

 

package com.test.socket.nio.blocked;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用阻塞模式的SocketChannel,ServerSocketChannel.
 * 为了同时连接多个客户端,需要使用多线程
 */
public class EchoServer {
	private int port = 8000;
	private ServerSocketChannel serverSocketChannel = null;
	private ExecutorService executorService;
	private static final int POOL_MULTIPLE = 4;
	
	public EchoServer() throws IOException {
		executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
				.availableProcessors() * POOL_MULTIPLE);
		//创建一个serverSocketChannel对象
		serverSocketChannel = ServerSocketChannel.open();
		//使得在同一个主机上关闭了服务器程序,紧接着再启动该服务器程序时,
		//可以顺利绑定相同的端口
		serverSocketChannel.socket().setReuseAddress(true);
		//与一个本地端口绑定
		serverSocketChannel.socket().bind(new InetSocketAddress(port));
		System.out.println("服务器启动...");
	}
	
	public void service(){
		while(true){
			SocketChannel socketChannel = null;
			try{
				socketChannel = serverSocketChannel.accept();
				//将每个客户连接都使用线程池中的一个线程来处理
				executorService.execute(new Handler(socketChannel));
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) throws IOException {
		new EchoServer().service();
	}
}
class Handler implements Runnable{
	private SocketChannel socketChannel;
	public Handler(SocketChannel socketChannel) {
		this.socketChannel = socketChannel;
	}
	public void run() {
		handler(socketChannel);
	}
	public void handler(SocketChannel socketChannel){
		try{
			Socket socket = socketChannel.socket();
			System.out.println("接收到客户连接,来自:"+socket.getInetAddress()+":"+socket.getPort());
			BufferedReader br = getReader(socket);
			PrintWriter pw = getWriter(socket);
			String msg = null;
			while((msg = br.readLine()) != null){
				System.out.println(msg);
				pw.println(echo(msg));
				if(msg.equals("bye")){
					break;
				}
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			try{
				if(socketChannel != null){
					socketChannel.close();
				}
			}catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	private PrintWriter getWriter(Socket socket)throws IOException{
		OutputStream socketOut = socket.getOutputStream();
		return new PrintWriter(socketOut,true);
	}
	private BufferedReader getReader(Socket socket)throws IOException{
		InputStream socketIn = socket.getInputStream();
		return new BufferedReader(new InputStreamReader(socketIn));
	}
	public String echo(String msg){
		return "echo:"+msg;
	}
}

 

package com.test.socket.nio.blocked;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SocketChannel;

public class EchoClient {
	private SocketChannel socketChannel = null;
	public EchoClient() throws IOException {
		socketChannel = SocketChannel.open();
		InetAddress ia = InetAddress.getLocalHost();
		InetSocketAddress isa = new InetSocketAddress(ia,8000);
		socketChannel.connect(isa);
		System.out.println("与服务器的连接建立成功");
	}
	public static void main(String[] args) throws IOException {
		new EchoClient().talk();
	}
	public void talk()throws IOException{
		try{
			BufferedReader br = getReader(socketChannel.socket());
			PrintWriter pw = getWriter(socketChannel.socket());
			BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
			String msg = null;
			while((msg = localReader.readLine()) != null){
				pw.println(msg);
				System.out.println(br.readLine());//接收服务器返回的消息
				//当输出的字符串为"bye"时停止
				if(msg.equals("bye")){
					break;
				}
			}
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			try{
				socketChannel.close();
			}catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	private PrintWriter getWriter(Socket socket)throws IOException{
		OutputStream socketOut = socket.getOutputStream();
		return new PrintWriter(socketOut,true);
	}
	private BufferedReader getReader(Socket socket)throws IOException{
		InputStream socketIn = socket.getInputStream();
		return new BufferedReader(new InputStreamReader(socketIn));
	}
}
 
分享到:
评论

相关推荐

    Java Socket学习---nio实现阻塞多线程通信

    我们将会分析`EchoServer.java`、`EchoClient.java`和`SocketUtils.java`这三个文件中的关键知识点。 首先,让我们从`EchoServer.java`开始。这是一个典型的回显服务器,它的主要任务是接收客户端发送的数据并...

    NIO实现网络通信,直接就能跑

    本示例通过两个类——EchoServer和EchoClient,展示了如何使用NIO实现基于TCP/IP协议的网络通信。 首先,我们来看`EchoServer`。这个类通常扮演服务端的角色,监听指定端口并接收客户端连接。在Java NIO中,服务器...

    DotNetty源码、编码解码器,IdleStateHandler心跳机制

    5. **性能优化**:DotNetty通过使用异步非阻塞I/O模型(NIO),实现了高度并发和低延迟。此外,它的内存管理机制(如ByteBuf)减少了不必要的对象创建和复制,提高了效率。开发者可以通过理解这些机制,进一步优化...

    java文件传输[归类].pdf

    - EchoServer和EchoClient类是核心类,负责服务器端和客户端的主要逻辑。 - 使用Java NIO的`ServerSocketChannel`和`SocketChannel`来处理服务器和客户端的连接,`Selector`和`SelectionKey`用于实现非阻塞特性,...

    java 进程之间的网络通信

    Java进程间的网络通信是计算机编程中的一个重要概念,它允许运行在不同或相同计算机上的多个...通过学习和理解EchoServer和EchoClient的实现,我们可以深入理解网络通信的基本原理,并在此基础上构建更复杂的网络应用。

    使用UDP实现Echo服务.rar_Echo Echo_java udp

    在实际应用中,你可以进一步扩展它,例如添加错误处理、多线程支持,或者使用NIO(非阻塞I/O)以提高性能。此外,由于UDP的特性,你可能还需要考虑数据包丢失和乱序的问题,尤其是在构建可靠通信系统时。

    漫谈Netty1.pdf

    Netty还提供了很多开箱即用的组件,如EchoServer和EchoClient。EchoServer是一个回显服务器,它将收到的每个消息直接返回给发送方,用于测试网络连接和消息的完整性。EchoClient则是一个回显客户端,它向服务器发送...

    JavaNetty.rar 消息通信 补充了很多注释

    Java Netty 是一个高性能、异步事件驱动的网络应用程序...通过阅读和理解"JavaNetty.rar"中的代码,特别是EchoClient和EchoServer的实现,你可以深入学习Netty的工作原理,以及如何利用它来构建高效的消息通信系统。

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

    首先,我们来看`EchoServer.java`。Echo服务器是一种简单的网络服务,它接收到客户端发送的数据后,原样返回。在Java中,我们可以使用`ServerSocket`类创建服务器端的套接字,并监听特定端口。当有客户端连接时,`...

    关于java的一些基本程序

    1. **EchoClient.java** 和 **EchoServer.java**:这两个文件可能涉及到TCP/IP协议中的回显服务。回显服务是一种常见的网络通信示例,其中客户端发送数据到服务器,服务器接收到数据后无修改地将其返回给客户端。在...

    netty实战教程、netty代码demo

    - **EchoClient**:对应于 EchoServer,是一个客户端,向服务器发送数据并接收回显。 - **ProtobufCodec**:展示了如何使用 Google 的 Protocol Buffers(protobuf)进行序列化和反序列化,以便在 Netty 中传输结构...

    Mina例子包含与spring整合

    可能涉及的文件包括配置文件(如`applicationContext.xml`),MINA的服务类(如`EchoServer`),客户端类(如`EchoClient`),以及相关的过滤器和协议处理器。 6. **配置示例**:在`applicationContext.xml`中,...

Global site tag (gtag.js) - Google Analytics