Java 套接字服务器

Posted

技术标签:

【中文标题】Java 套接字服务器【英文标题】:Java Socket Server 【发布时间】:2013-02-11 11:25:19 【问题描述】:

我已经失去它了......

我通过 FlashDevelop (AS3) 构建了一个简单的 Flash 应用程序,我希望它能够与服务器通信。然后我用代码创建了一个简单的 Socket Java 应用程序:

Main.java:

import org.xsocket.connection.*;

public class Main

    protected static IServer srv = null;

    public static void main(String[] args) 
    
        try
        
            srv = new Server(8090, new xSocketDataHandler()); 
            srv.run();
        
        catch(Exception ex)
        
            System.out.println(ex.getMessage());
        
    

    protected static void shutdownServer()
    
        try
        
            srv.close();
        
        catch(Exception ex)
        
            System.out.println(ex.getMessage());
                
    

和xSocketDataHandler.java:

import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.channels.ClosedChannelException;
import java.util.*;
import org.xsocket.*;
import org.xsocket.connection.*;


public class xSocketDataHandler implements IDataHandler, IConnectHandler, IDisconnectHandler

    private Set<INonBlockingConnection> sessions = Collections.synchronizedSet(new HashSet<INonBlockingConnection>());

    public boolean onData(INonBlockingConnection nbc) throws IOException, BufferUnderflowException, ClosedChannelException, MaxReadSizeExceededException 
    
        try
        
            String data = nbc.readStringByDelimiter("\0");

            if(data.trim().length() > 0)
               
                System.out.println("Incoming data: " + data);

                if(data.equalsIgnoreCase("<policy-file-request/>"))
                
                    nbc.write("<cross-domain-policy>" +
                            "<allow-access-from domain=\"*\" secure=\"false\" />" +
                            "<allow-access-from domain=\"*\" to-ports=\"8090\"/>" +
                            "</cross-domain-policy>\0");
                    return true;
                

                String[] message = data.split("~");

                sendMessageToAll(nbc, message[0], message[1]);

                if(message[1].equalsIgnoreCase("SHUTDOWN"))
                    Main.shutdownServer();                
            
        
        catch(Exception ex)
        
            System.out.println("onData: " + ex.getMessage());
        

        return true;
    

    private void sendMessageToAll(INonBlockingConnection nbc, String user, String message)
    
        try
        
            synchronized(sessions)
            
                Iterator<INonBlockingConnection> iter = sessions.iterator();

                while(iter.hasNext())
                
                    INonBlockingConnection nbConn = (INonBlockingConnection) iter.next();

                    if(nbConn.isOpen())
                        nbConn.write("<b>" + user + "</b>: " + message + "<br />\0");
                
            

            System.out.println("Outgoing data: " + user + ": " + message);
        
        catch(Exception ex)
        
            System.out.println("sendMessageToAll: " + ex.getMessage());
                    
    

    public boolean onConnect(INonBlockingConnection nbc) throws IOException, BufferUnderflowException, MaxReadSizeExceededException
    
        try
        
            synchronized(sessions)
            
                sessions.add(nbc);            
            

            System.out.println("onConnect");
        
        catch(Exception ex)
        
            System.out.println("onConnect: " + ex.getMessage());
        

        return true;
    

    public boolean onDisconnect(INonBlockingConnection nbc) throws IOException
    
        try
        
            synchronized(sessions)
            
                sessions.remove(nbc);            
            

            System.out.println("onDisconnect");
        
        catch(Exception ex)
        
            System.out.println("onDisconnect: " + ex.getMessage());
                

        return true;
    

所以,问题是:

我启动了 Java 应用程序,它运行良好。我启动我的 Flash 应用程序并运行它,创建套接字对象,连接到我的服务器(全部在我的计算机中),服务器获取连接尝试,但是,在:

nbc.readStringByDelimiter("\0");

它说 nbc 已关闭,服务器捕获异常: "onData: channel is closed (read buffer size=0)"

有谁知道为什么我总是得到这个?不管我怎么写,使用 Socket、XMLSocket、xSocketDataHandler 或任何东西,我总是收到关闭通道错误。

我做错了什么??

谢谢。

编辑1:

AS3 代码:

这是我的 Socket 类:

import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
/**
* ...
* @author 9MS
*/
public class GameSocket extends Socket 

    private var host:String;
    private var port:int;

    public function GameSocket(host:String="187.127.89.158", port:int=8090)
    
        super(host, port);

        socketConnect();
    

    public function socketConnect():Boolean 


        addEventListener(Event.CONNECT, onConnect);
        addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
        addEventListener(Event.CLOSE, onClose);
        addEventListener(IOErrorEvent.IO_ERROR, onError);
        addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecError);

        try 
            connect(this.host, this.port);
        
        catch (e:Error) 
            trace("Error on connect: " + e);
            return false;
        
        return true;
    

    public function sendData(msg:String):void 
        msg += "\0";

        try 
            writeUTFBytes(msg);
            flush();
            trace("Message sent: " + msg);
        
        catch(e:Error) 
            trace("Error sending data: " + e);
        

    

    private function onConnect(e:Event):void 
        trace("Connected: "+e);
    

    private function onResponse(e:ProgressEvent):void 
        trace("Receiving Data: " + e);

        var resp:String = readUTFBytes(bytesAvailable);

    

    private function onClose(e:Event):void 
        trace("Connection Closed: " + e);
        close();
    

    private function onError(e:IOErrorEvent):void 
        trace("IO Error: " + e.text);
        close();
    

    private function onSecError(e:SecurityErrorEvent):void 
        trace("Security Error: " + e.text);
        close();
    


【问题讨论】:

你看过这个帖子giantflyingsaucer.com/blog/?p=205 是的,这是我第一次使用的教程,但是您可以在帖子的 cmets 看到更多人遇到我的问题... 你能贴出AS3代码吗?也许闪光灯关闭连接? (即使用本地变量作为套接字或超出范围) 刚刚发布。我只是调用了socket = new GameSocket();,它已经在构造函数中通过socketConnect(); 启动了连接。 所以,我已经将我的 java 文件发送到服务器,并且我在那里做同样的事情,我的服务器在我的计算机上。这样做,我收到Incoming data: &lt;policy-file-request/&gt;(“\0”是我的 Socket 内容),但它在我发送策略信息后关闭了 Socket。有什么新想法吗? 【参考方案1】:

所以,我已经解决了这个问题。在通过套接字进行 Flash 通信中一个非常重要的事情是 Flash 打开套接字桥,请求策略文件,然后关闭它。因此,在您的服务器中,您必须接收连接、检查策略文件请求、发送策略文件并关闭网桥。 Flash收到策略文件后,会再次打开连接,正常通信,无需再次请求策略文件。

因此,在获得新连接后,您必须正常启动您的逻辑,但是,如果您收到策略文件请求,只需使用策略文件回答并关闭连接。

【讨论】:

以上是关于Java 套接字服务器的主要内容,如果未能解决你的问题,请参考以下文章

Java 套接字服务器

Java HTTP/2 服务器套接字

Java - 异步套接字通道无法连接到远程异步服务器套接字通道

Java套接字服务器

Java 客户端/服务器套接字损坏的管道

套接字阻止在 Java 服务器和 Python 客户端之间发送消息