1. 一点儿废话
这篇博文拖泥带水的搞了很久,一直没有发出来。我还是要坚持自己是mina学习之路的。
今天我们来解决一下如何来搞定一个server端,多个client的socket通信方式。
2.服务端的支持
2.1 ServerSocket.accept()
Java doc:
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
监听一个Socket连接并接受他。这个方法会一直阻塞直到有一个Socket连接创建。(
也就说,accept方法会等待客户端连接,如果没有连接,他将一直等待。)
2.2 Server端支持多个客户端
当服务单通过accept方法取得一个socket连接后,他应该取做自己该做的工作,例如从socket中取得客户端给的命令等等,所以他需要一个单独的线程去处理。而服务端应该接到一个客户端的socket连接后,继续等待下一个客户端的到来。所以实现代码应该像下面这样:
while (true) {
try {
Socket client = server.accept();
// 异步客户端连接处理
}
catch (IOException e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e.getCause());
}
}
2.3 整体服务端代码
为了测试,我想服务端可以用一个线路在后台运行,所以实现了Runnable接口,如下:
package com.ex.io.socket.thread;
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.ex.io.socket.page.Console;
public class MultiClientCmdSocketServer implements Runnable {
public static final Log LOG = LogFactory.getLog(MultiClientCmdSocketServer.class);
public static final int SERVER_PROT = 8100;
private ServerSocket server;
private Console console;
private Executor executer;
private boolean interruptable = false;
public MultiClientCmdSocketServer() {
init();
}
private void init() {
try {
server = new ServerSocket(SERVER_PROT);
}
catch (IOException e) {
throw new RuntimeException(e.getMessage(), e.getCause());
}
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(10);
executer = new ThreadPoolExecutor(10, 100, 1, TimeUnit.HOURS, workQueue);
}
@Override
public void run() {
while (true && !interruptable) {
try {
Socket client = server.accept();
executer.execute(new SocketRunnable(client, console));
}
catch (IOException e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e.getCause());
}
}
}
public void setConsole(Console console) {
this.console = console;
}
public void setInterruptable(boolean interruptable) {
this.interruptable = interruptable;
}
private class SocketRunnable implements Runnable {
private Socket client;
private Console console;
public SocketRunnable(Socket client, Console console) {
this.client = client;
this.console = console;
}
@Override
public void run() {
LOG.info(">>>Client[" + client + "]接受命令开始...");
console.info("Receive command from client [" + client + "] start ...");
BufferedReader reader = null;
PrintWriter writer = null;
try {
reader =new BufferedReader(new InputStreamReader(client.getInputStream()));
writer = new PrintWriter(client.getOutputStream());
while (true) {
String cmd = reader.readLine();
writer.print("roger : " + cmd + "\n");
console.info("roger from client [" + client + "]: " + cmd);
writer.flush();
if (StringUtils.endsWithIgnoreCase(":quit", cmd)) {
break;
}
}
client.close();
}
catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e.getCause());
}
finally {
IOUtils.closeQuietly(reader);
IOUtils.closeQuietly(writer);
}
console.info("Receive cmd from client [" + client + "] end");
LOG.info("<<<Client[" + client + "]接受命令结束.");
}
}
}
3. 客户端支持
说完服务端,客户端就显得很简单,只需要有真是的客户端连上,获自己写个线程模拟一下。为了不从系统IO中获取输入,我用了一个BlockingQueue。
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.ex.io.socket.page.Console;
public class SocketClientRunnable implements Runnable {
public static final Log LOG = LogFactory.getLog(SocketClientRunnable.class);
private String name;
private Console console;
private BlockingQueue<String> inputQueue = new LinkedBlockingQueue<String>(20);
public SocketClientRunnable(String name, Console console) {
this.name = name;
this.console = console;
}
public void putCmd(String cmd) {
try {
inputQueue.put(cmd);
}
catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e.getCause());
}
}
@Override
public void run() {
console.info(">>>Client [" + name + "] start >>>");
BufferedReader reader = null;
BufferedWriter writer = null;
try {
// Get socket from server
Socket server =
new Socket(InetAddress.getLocalHost(), MultiClientCmdSocketServer.SERVER_PROT);
reader = new BufferedReader(new InputStreamReader(server.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(server.getOutputStream()));
while (true) {
String cmd = inputQueue.take();
console.info(name + " puts command [" + cmd + "] to server");
writer.write(cmd.concat("\n"));
writer.flush();
if (StringUtils.endsWithIgnoreCase(":quit", cmd)) {
break;
}
String serverRoger = reader.readLine();
String rogerMsg = "Server feed back for client[" + name + "] : " + serverRoger;
console.info(rogerMsg);
LOG.info(rogerMsg);
}
server.close();
}
catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e.getCause());
}
finally {
IOUtils.closeQuietly(reader);
IOUtils.closeQuietly(writer);
}
console.info("<<<Client [" + name + "] end <<<");
}
}
4. 如果你比较有余力,还可以用Java Swing演示一下
上面代码中的console就是为向Swing中打日志,如果不需要,直接删除
5. 小结一下
- 服务端支持多客户端,增加多线程处理,让主线程等待客户端的到来
- 客户端连接,可以通过线程模拟
就这么简单
- 大小: 47 KB
分享到:
相关推荐
mina-core-2.0.0-M6.jar mina-example-2.0.0-M6.jar mina-filter-codec-netty-2.0.0-M6.jar mina-filter-compression-2.0.0-M6.jar mina-integration-beans-2.0.0-M6.jar mina-integration-jmx-2.0.0-M6.jar mina-...
**Android-MinaSocket:基于Mina的高效Socket长连接库** 在移动应用开发中,尤其是Android平台,实时性与稳定性是许多应用场景的核心需求,比如在线游戏、即时通讯、物联网设备等。在这种背景下,使用Socket进行长...
在这个"网络编程(socket、NIO、mina)---demo"的主题中,我们将深入探讨三个关键概念:Socket编程、非阻塞I/O(Non-blocking I/O,简称NIO)以及Apache Mina框架。这些技术广泛应用于构建高性能、高并发的网络应用...
在这个场景中,我们关注的是MINA的核心组件以及两个特定的过滤器和传输组件:`mina-core-2.0.0-RC1.jar`、`mina-filter-compression-2.0.0-RC1.jar`和`mina-transport-apr-2.0.0-RC1.jar`。 **MINA Core (mina-core...
mina-filter-compression-2.0.7.jar,mina 过滤器jar包,核心包之一
### HPsocket 封包与mina对接 #### 一、HPsocket概述 HPsocket是一个高性能、跨平台的TCP/UDP/串口通信中间件库,它提供了丰富的API接口和灵活的事件驱动模型,使得用户可以方便地开发自己的网络应用程序。本文将...
Apache Mina是一个开源框架,主要用于构建高性能、高可用性的网络应用程序。它主要关注网络通信的I/O层...通过深入学习和实践这些知识,你将能够利用Mina框架构建出高效、稳定的网络服务,应对高并发场景下的通信挑战。
mina-core-2.0.0-M1.jar/mina-example-1.0.5.jar/slf4j-jdk14-1.6.1.jar/slf4j-log4j12-1.6.1.jar mina 所用jar
mina-integration-ognl-2.0.0-M4.jar mina-integration-ognl-2.0.0-M4.jar
mina-transport-apr-2.0.7.jar是MINA对Apache Portable Runtime (APR)的支持,APR是一个库,提供了操作系统级别的接口,如socket和线程,可以提升MINA在某些平台上的性能。 mina-integration-jmx-2.0.7.jar提供了...
mina-integration-beans-2.0.0-M4.jar mina-integration-beans-2.0.0-M4.jar
标题中的"apache-mina-2.0.16-jar包-代码.zip"表明这是一个包含Apache Mina 2.0.16版本源代码的JAR文件压缩包。这个压缩包通常用于开发者进行源码级别的学习、调试或定制工作。通过解压这个文件,你可以获得Mina库的...
Mina和Socket是两种常见的网络通信框架和技术,它们在Java编程环境中被广泛使用。本篇文章将深入探讨如何使用Mina与Socket实现通信,并提供客户端和服务端的实现代码概述。 Mina(全称“MINA: Minimalistic ...
标题中的"Apache-Mina-2.rar"和"mina-mina-core-1.1.3"表明这是关于Apache Mina 2.x版本,特别是其核心模块的1.1.3版本。 Apache Mina的名称来源于"Multi-purpose Infrastructure for Network Applications",它...
mina-core-2.0.0-M1-sources.jar是构建mina框架的主要文件
mina-core-2.0.0-RC1-sources.jar
综上所述,MINA-2.0.0-M3源码的学习将涵盖Java网络编程、非阻塞I/O、事件驱动编程、协议处理等多方面知识,对于想要深入了解网络应用开发和优化的Java开发者来说,是一份宝贵的资料。通过研究MINA的源代码,不仅可以...
mina-transport-apr-2.0.2.jar
《mina-core-2.0.0-M1.jar与SLF4J:构建高效网络通信与日志记录》 mina-core-2.0.0-M1.jar是Apache Mina项目的核心库,它是一个高度可扩展的网络通信框架,主要用于构建高性能、高效率的服务端和客户端应用程序。...
Apache Mina 传输原始套接字Apache mina Rawsocket 传输使用本机库 jnetpcap 1.4.r1425 来自: ://jnetpcap.com/download 请参阅: : 用于 NIC(网络接口卡)的 IoAcceptor //10.10.10.1 is one of nic's ip ...