Java套接字服务器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java套接字服务器相关的知识,希望对你有一定的参考价值。

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

我通过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("");

            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>");
                    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 />");
                }
            }

            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("");

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

有谁知道为什么我总能得到这个?无论我如何编写它,使用Socket,XMLSocket,xSocketDataHandler,或者任何时候,我都会收到封闭的通道错误。

我究竟做错了什么??

谢谢。

EDIT1

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 += "";

        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();
    }

}
答案

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

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

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

Java通过套接字传输多个文件

iOS 上的 VoIP 套接字 - 未收到通知

Java 套接字服务器

Java Web 实战 15 - 计算机网络之网络编程套接字

Java套接字服务器

Java 套接字 ClassCastException