|
源代码网推荐
2 Java多线程服务器
基本的通信做到以后就是修改代码增加功能了,这里我们必须让Java能支持多个线程的连接,这才是服务器呀。
import java.io.*; import java.net.*; public class Server extends ServerSocket{ //服务端口号常量(as要求必须大于1024,小于65535) private static final int SERVER_PORT = 10086; //构造函数 public Server() throws IOException{ super(SERVER_PORT); //监听新连接,为每个连接分配一个线程,将新的连接传入独立线程 Socket socket = accept(); new SocketThread(socket); } //入口函数... public static void main (String[] args) throws IOException{ new Server(); } //建一个类,该类属于独立的线程,他的每个实例都会在独立的线程里运行 class SocketThread extends Thread{ //申明流的空间在独立线程里了,因为他属于传送时所需,主线程只是监听有没有新连接 private Socket client; private BufferedReader in; private PrintWriter out; private String src; //构造函数 public SocketThread(Socket socket) throws IOException{ //初始客户端的连接为该线程传入的连接 client = socket; //初始流在进来后读取前,和写入后发送前所存放的空间 in = new BufferedReader(new InputStreamReader(client.getInputStream())); out = new PrintWriter(client.getOutputStream(),true); //准备工作完毕,启动该线程 start(); } public void run(){try { //循环等待读取信息 while(true){ //读取行信息,注意是以换行符结束的 src = in.readLine(); //如果发送"close",就跳出循环(断开连接) if(src.equals("close")){ break; } //在收到的信息前加是标识并发回(注意结尾加" ",这是as的XMLSocket读入每条信息的条件.as3的Socket不需要) out.println("rev: "+src+" "); //以上out.println("xx")相当于out.write("xx");out.flush();的执行效果 System.out.println("msg is "+src) } //关闭连接 close(); }catch(IOException e){ }catch(NullPointerException e){ System.out.println("client closed"); }} } }
修改后的Java主线程监听是否有新的连接,如果有就把这个连接分配到新的线程,让他去监听消息,而自己继续监听连接,这样的思路是不是很清晰呢? 仔细看看其实不是很难,大部分的代码都和前面的一样,只是循环监听信息的代码被放到的独立的线程里面。 关于多线程和一些Java的技术问题,为了对大家负责,我依然谨慎言语,以免误导大家。 现在你可以启动多个as对Java进行连接,并且他们之间互不干扰。一个线程对应一个连接,底层的工作非常透明,管理非常容易 3 AS 通过Java数据转发实现P2P通信
谈到这里,其实要实现这步就非常容易了,原理上只要将本来Java收到后返回的信息,发到别人这里去,就可以了。原理如下所示
flash_1 -> Java -> flash_2 flash_2 -> Java -> flash_3 flash_3 -> Java -> flash_1
这样任何两个flash之间都能通过java转发了,现在只有一个问题,就是Java怎么知道我的信息要发给谁?其实很简单我们在每个连接连入的时候发送一条注册信息,让Java知道我的名字,而别人只要在字符串前加上我的名字就可以了。 那么在Java里 我们需要两个功能
个是增加和删除自己的标识 是识别字符串中哪些是名字,哪些是信息 这里我们用到方法是<空格> "r s1";这样的一条信息过去,Java服务器要处理为该连接添加一个标识s1,而在这以后任何客户端只要发送 "s1 Hello";就会把"Hello"这个字符串发送给标识为s1的客户端,这样两个flash之间就完全实现了数据互通 "u s1";当离开的时候可以用这个代码来删除s1的标识符 为了简单和安全,我们可以暂设为标识必须是两位,以字母开头,这样的组合已经超过千种,绝对够用了。 这样只要判断空个所出现的位置即可,如果是第二位就是注册或卸载标识,如果是第三位就是字符转发了,如果都没有,那就是错误信息。 把上面的Run里的out.println("rev: "+src+" ");改成以下信息就可以判断信息是注册还是卸载了
//屏蔽所有长度小于4的信息,不做处理. if(line.length()<4){ out.write("error: length<4"); out.flush(); line = in.readLine(); continue; } //命令字符 if (line.charAt(1)==" "){ //相应客户端命令请求 name = line.substring(2); switch (line.charAt(0)) { case "r": //注册客户端 if (!registered && name.length()==2){ //为自己加一个ID Server.clientID.put(name,client); registered = true; //返回注册成功 out.write("registeration successed"); out.flush(); } break; case "u": //删除客户端 Server.clientID.remove(name); registered = false; break; } }else if (line.charAt(2)==" "){ //这里是转发代码; }
当然这里用的一些API在前面还要声明过。在线程类里增加两条申明
private String name; private boolean registered;
构造函数里
registered = false;
当然最重要的是还要在Server的主线程里声明一个放ID的容器
public static HashMap clientID = new HashMap();
这样每个连接都有自己的ID了
现在要做的是在转发了,在上面的转发代码的地方写
send(line.substring(0,2),line.substring(3)); 当然send函数还没有定义呢,现在定义 复制内容到剪贴板代码: public boolean send(String id, String src) throws IOException { //读取标识的地址 Socket socket = (Socket)Server.clientID.get(id); if (socket != null){ out = new PrintWriter(socket.getOutputStream(), true); out.write(src); out.flush(); return true; }else{ return false; } }
这里我加入了判断id是否存在,当不存在就没有任何操作,并且将操作结果成功与否返回,在send的时候就可以分类成功或不成功分别做什么了。
马上来开两个AS吧,用到我们刚才第一章节里自己封装的as2,把加载成功的地方改成send("r c1
");和send("r c2
"); Action Script 2
//file1 var SERVER_PORT:Number = 10086; var SERVER_IP:String = "127.0.0.1"; conn:Socket = new Socket(); conn.connect(SERVER_IP,SERVER_PORT); conn.onConnect = function (success:Boolean){ if (success){ write("r c1"); flush(); } } //file2 var SERVER_PORT:Number = 10086; var SERVER_IP:String = "127.0.0.1"; conn:Socket = new Socket(); conn.connect(SERVER_IP,SERVER_PORT); conn.onConnect = function (success:Boolean){ if (success){ write("c2 hello"); flush(); } }
依次运行file1,file2看看,file2运行的时候是不是成功收到了一个hello呢?嘿嘿。 这样做虽然底层还是没有实现P2P,但是效果已经达到,如果还是觉得不够理想,那么可以每个客户端都绑定一个Java的ServerSocket,负责收信息,并转发给同绑定Flash,这样虽然没有实现swf的p2p,但是在底层已经p2p了 资源下载
源代码网供稿. |