Mult-Echo转发服务器

2014年5月13日 由 Creater 留言 »

GPRS模块的数据需要发送到本地控制台,与传统的GSM模块以短信作为传输媒介传输不同,这种方案按理想状态有以下两种方式:
(要找一台公网IP的服务器还是很不容易,网上找则需要花钱,刚好我家里的电脑是ADSL拨号,有公网IP,将服务器部署在上面最好不过)

1.GPRS模块之间可通信
但是事实上除非花大钱购买专有IP,否则现在还不能做到点对点的通信,即使是在PC机上完成P2P,也是需要第三方公网服务器的协调才能完成。以下为这种理想情况的框架图。
1

2.通过第三方公网服务器转发
如果GPRS点之间可以通信,那么可以使用该服务器来协调P2P的建立。但是实际上并不能点对点通信,所以只有选择通过第三方服务器的转发。以下是可实现的框架图。
3

作为公网转发服务器,要克服GPRS模块建立网络后容易异常掉线这种情况。当然作为服务器端,功能需求非常少,只需转发即可,代码也就很简单了。

package reflectServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Echo-transfer服务器
 */
public class EchoServer {

	private final static int BUFFER_SIZE = 512;
	private final static int PORT = 3333;
	private Selector selector = null;
	private ServerSocketChannel ssc = null;

	public static void main(String[] args) throws IOException {
		EchoServer server = new EchoServer();
		server.start();
	}

	private static void print(String s) {
		System.out.println(s);
	}

	private List<SocketChannel> socketsChanel = new ArrayList<SocketChannel>();

	public void pop(SocketChannel sc) {
		socketsChanel.remove(sc);
	}

	public void push(SocketChannel sc) {
		socketsChanel.add(sc);
	}

	public EchoServer() throws IOException {
		selector = Selector.open();
		ssc = ServerSocketChannel.open();
		ssc.socket().bind(new InetSocketAddress(PORT));
		ssc.socket().setReuseAddress(true);
		ssc.configureBlocking(false);
		ssc.register(selector, SelectionKey.OP_ACCEPT);
		print("服务器启动,准备好连接...");
	}

	public void start() throws IOException {
		ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
		
		while (selector.select() > 0) {
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			for (SelectionKey key : selectionKeys) {
				if (key.isAcceptable()) {
					SocketChannel sc = ssc.accept();
					print("有新的连接!地址:" + sc.socket().getRemoteSocketAddress());
					sc.configureBlocking(false);
					sc.register(selector, SelectionKey.OP_READ);
					push(sc);
				}

				if (key.isReadable()) {
					SocketChannel sc = (SocketChannel) key.channel();
					//print("有新的读取!地址:" + sc.socket().getRemoteSocketAddress());
					buffer.clear();
					try {
						int bytes = sc.read(buffer);
						if (-1 == bytes) {
							print("连接断开");
							key.cancel();
							sc.close();
							pop(sc);
							continue;
						}
					} catch (Exception e) {
						pop(sc);
					}

					buffer.flip();
					/*byte[] b = new byte[buffer.limit()];
					buffer.get(b);
					String s = new String(b);
					print("读取的内容为:" + s);
					buffer.clear();
					s = "echo: " + s;
					buffer.put(s.getBytes());
					buffer.flip();*/
					//print("共有多少套接字连接:" + socketsChanel.size());
					for (SocketChannel socketSend : socketsChanel) {
						if (socketSend != sc)
							try {
								socketSend.write(buffer);
								buffer.flip();
							} catch (Exception e) {
								pop(socketSend);
								e.printStackTrace();
								break;
							}
					}
				}
			}
			selectionKeys.clear();
		}
	}
}
广告位

发表评论

你必须 登陆 方可发表评论.