当前位置:首页 > 开发 > 编程语言 > 网络编程 > 正文

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

发表于: 2014-09-12   作者:商人shang   来源:转载   浏览:
摘要: 本次使用nio实现socket客户端和服务端的通信,并且在服务端为每一个新建的连接创建一个线程负责维持和客户端的通信。 使用nio实现的阻塞的socket与普通方式实现的通信相比较仅仅是实现方式不同,其实质的运行原理是一样的。在此仅仅作为一个nio的入门示例。 nio来做socket主要用到两个类ServerSocketChannel(服务器socket)和SocketChannel(客户端s

本次使用nio实现socket客户端和服务端的通信,并且在服务端为每一个新建的连接创建一个线程负责维持和客户端的通信。

使用nio实现的阻塞的socket与普通方式实现的通信相比较仅仅是实现方式不同,其实质的运行原理是一样的。在此仅仅作为一个nio的入门示例。

nio来做socket主要用到两个类ServerSocketChannel(服务器socket)和SocketChannel(客户端socket)。

 

Channel的简单介绍:ServerSocketChannel和SocketChannel。Java NIO的通道类似流,但又有些不同:

 1. 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。

 2. 通道可以异步地读写。

 3. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。

 

Server端程序:

package com.henushang.socket.chapter4nio;

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

import com.henushang.socket.util.SocketUtils;

public class EchoServer {

	private int port = 8000;
	private ServerSocketChannel serverSocketChannel;
	private ExecutorService executorService;
	private final int POOL_SIZE = 4;

	public EchoServer() throws Exception {
		executorService = Executors.newFixedThreadPool(Runtime.getRuntime()
				.availableProcessors() * POOL_SIZE);
		serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.socket().bind(new InetSocketAddress(port));
		System.out.println("等待连接...");
	}

	public void service() {
		SocketChannel socketChannel = null;
		while (true) {
			try {
				System.out.println("waitting for connect...");
				socketChannel = serverSocketChannel.accept();
				System.out.println("get the connect...");
				Thread.sleep(500);
				executorService.execute(new Handler(socketChannel));
			} catch (IOException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
	}

	public static void main(String[] args) throws Exception {
		new EchoServer().service();
	}

	class Handler implements Runnable {
		private SocketChannel socketChannel = null;

		public Handler(SocketChannel socketChannel) {
			this.socketChannel = socketChannel;
		}

		@Override
		public void run() {
			handler(socketChannel);
		}

		private void handler(SocketChannel socketChannel) {
			System.out.println("new connection accepted:"
					+ socketChannel.socket().getInetAddress() + ":"
					+ socketChannel.socket().getPort());
			try {
				BufferedReader reader = SocketUtils
						.getReader(this.socketChannel);
				PrintWriter pw = SocketUtils.getWriter(this.socketChannel);
				String msg = null;
				while (true) {
					if ((msg = reader.readLine()) != null) {
						try {
							Thread.sleep(20000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						System.out.println(msg);
//						pw.write(SocketUtils.echo(msg)+"\r\n");
						pw.println(SocketUtils.echo(msg));
						pw.flush();
						if ("bye".equals(msg)) {
							break;
						}
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				SocketUtils.close(socketChannel);
			}
		}
	}
}

 

Client端程序:

package com.henushang.socket.chapter4nio;

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

import com.henushang.socket.util.SocketUtils;

public class EchoClient {
	
	private SocketChannel socketChannel;
	private int port = 8000;
	
	public EchoClient() throws Exception {
		socketChannel = SocketChannel.open();
		InetAddress inetAddress = InetAddress.getLocalHost();
		InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, port);
		socketChannel.connect(inetSocketAddress);
		System.out.println("准备连接服务器");
	}
	
	public static void main(String[] args) throws Exception {
		new EchoClient().talk();
	}
	
	public void talk() {
		try {
			BufferedReader reader = SocketUtils.getReader(socketChannel.socket());
			PrintWriter pw = SocketUtils.getWriter(socketChannel.socket());
			BufferedReader localreaderReader = new BufferedReader(new InputStreamReader(System.in));
			String msg = null;
			while ((msg = localreaderReader.readLine()) != null) {
				System.out.println(msg);
				pw.println(msg);
				pw.flush();
				System.out.println(reader.readLine());
				if ("bye".equals(msg)) {
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			SocketUtils.close(socketChannel);
		}
		
	}
}

 

 

SocketUtils:(与以前的一样)

package com.henushang.socket.util;

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.Socket;
import java.nio.channels.SocketChannel;

public class SocketUtils {
	
	public static PrintWriter getWriter(Socket socket) throws IOException {
		OutputStream os = socket.getOutputStream();
		return new PrintWriter(os);
	}
	
	public static PrintWriter getWriter(SocketChannel socketChannel) throws IOException {
		return getWriter(socketChannel.socket());
	}
	
	public static BufferedReader getReader(Socket socket) throws IOException{
		InputStream is = socket.getInputStream();
		return new BufferedReader(new InputStreamReader(is, "UTF-8"));
	}
	
	public static BufferedReader getReader(SocketChannel socketChannel) throws IOException{
		return getReader(socketChannel.socket());
	}
	
	public static void close(Socket socket) {
		try {
			if (socket != null) {
				socket.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void close(SocketChannel socketChannel) {
		try {
			if (socketChannel != null) {
				socketChannel.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static String echo(String msg) {
		return "echo:" + msg;
	}
}

 

 

 

 

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

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
除了普通的Socket与ServerSocket实现的阻塞式通信外,java提供了非阻塞式通信的NIO API。先看一下NI
从JDK 1.4开始,Java提供的NIO API来开发高性能网络服务器,前面介绍的网络通信程序是基于阻塞式API
用java实现socket C/S通信很简单,很多教科书上都有。但是这些通信模型大都是阻塞式的,其弊端也很
前几天我们公司C语言组的人需要一个基于socket的报文接收器来方便他们测试项目,我花了小半天给他们
一、 描述 Java 提供的 NIO API 来开发高性能网络服务器, JDK 1.4 以前 的网络通信程序是基于阻塞
先来看一段单线程的原始代码(代码中有详细的注释): 服务器(TCPServer.java): import java.net.*;
先来看一段单线程的原始代码(代码中有详细的注释): 服务器(TCPServer.java): import java.net.*;
前言 首先,说一件无关的事情,萧鼎的诛仙2更新了,这一等就是一年啊,今天中午思考去阿里用神马花
环境准备 【服务器端】 JDK1.6,“java.net”包对网络编程提供了非常全面的支持,包括Socket 开发环
环境准备 【服务器端】 JDK1.6,“java.net”包对网络编程提供了非常全面的支持,包括Socket 开发环
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号