簡體   English   中英

如何在Java Server Client中通過套接字傳遞對象

[英]How to pass object by socket in java Server Client

我是Java套接字的新手,我看到了很多示例,但我不明白如何將參數從服務器傳遞到客戶端,反之亦然。 我的目的地是傳遞對象,這就是為什么我使用對象I / O流的原因。

我必須對服務器和播放器進行分類。

public class Server extends Thread{
public static final int TEST = 165;

ServerSocket serverSocket;
InetAddress address;

Player playerWhite;

public Server() {               
    start();
}

@Override
public void run() {
    try
    {
        address = InetAddress.getLocalHost();
        serverSocket = new ServerSocket(6000);
        playerWhite = new Player();

        System.out.println("server waits for players");
        playerWhite.socket = serverSocket.accept();
        playerWhite.start();
        sendTestMessage(playerWhite);

    } 
    catch (IOException ex) 
    {
        Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
    }               
}

public void sendTestMessage(Player player) throws IOException
{
    ObjectOutputStream testToClient = new ObjectOutputStream(player.socket.getOutputStream());        
    testToClient.write(TEST); 
    testToClient.flush();        
}

和Player類:

public class Player extends Thread {   
Socket socket;

Player() throws IOException
{
    socket = new Socket(InetAddress.getLocalHost(), 6000);
}

@Override
public void run() {
    try {            
        listenTestStream();
    } 
    catch (IOException | ClassNotFoundException ex) 
    {
     Logger.getLogger(CheckerPlayer.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public void listenTestStream() throws IOException, ClassNotFoundException
{
    ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
    int message = ois.readInt();

    //To test
    System.out.println("Server listened: " + message);
}

我在另一個類中創建Server對象時執行它。

在測試此應用程序時,我發現有時客戶端比服務器更快。 是否可以讓他“等待”服務器響應? 感謝您的答復。

編輯1:問題解決方案:

從外部我們應該創建:

Player player = new Player(); // (class player extends from Thread) player.start();

並刪除Player變量-是沒有必要的,因此我們只需要Socket:服務器:

Socket playerWhiteSocket

public void run() {
try
{
    serverSocket = new ServerSocket(PORT);
    playerWhiteSocket = serverSocket.accept();
    sendMessage(playerWhiteSocket, "Hello");
} 
catch(IOException | ClassNotFoundException ex)
{}

public void sendMessage(Socket socket, String message) throws IOException
{
    ObjectOutputStream testToClient = new ObjectOutputStream(socket.getOutputStream());        
    testToClient.writeObject(message);
    testToClient.flush();        
}

在Player類中,我們需要get方法:

public String receiveMessage() throws IOException, ClassNotFoundException
{
    //socket is a variable get from Player class socket = new Socket("severHost", PORT);
    ObjectInputStream messageFromServer = new ObjectInputStream(socket.getInputStream()); 
    String message = (String) messageFromServer.readObject();
    return message;
}   

我建議做這個公共無效的start(){

try {
        ServerSocket = new ServerSocket(this.port,10,this.localAddress);

        // set timeout if you want
        //this.clientServerSocket.setSoTimeout(timeout);
        // infinity loop 
        while(true)
        {
            //wait for a client connection
            Socket socket = ServerSocket.accept();
            // start thread for every new client
            Thread t = new Thread(new AcceptClients(this.socket));
            t.start();
            System.out.println(L"new client connected");
            // call garbage collector and hope for the best
            System.gc();
        }
    } catch (IOException e) {
        System.out.println("IO Error");
        e.printStackTrace();
    }
}

然后在另一堂課

public class AcceptClients implements Runnable{

// socket
private Socket socket;

public AcceptClients (Socket socket){
    this.socket = socket;
}
@Override
public void run() {
    // what happens if a client connect
}

}

我總是使用它,並且效果很好

建議的更改。

  1. 僅創建一次ServerSocket。 如果已完成,則不會收到“ Address already in use ”錯誤

  2. 創建服務器套接字后,線程應處於while (true)循環中,以接受來自客戶端的連接。

  3. 創建客戶端套接字后,將該套接字傳遞給線程。

  4. 現在,使用Player將通信從服務器發送到客戶端套接字。 因此,您還需要一個類似於PlayerClient類,該類創建服務器IP和端口的套接字。 現在,PlayerClient應該再創建一個線程來處理IO操作,就像您在服務器上所做的一樣。 在這種情況下,不在客戶端的while循環中創建套接字。 它一次創建一個到服務器的套接字。 現在,您可以從多台計算機上運行此PlayerClient程序。

  5. 如果僅發送原始類型,請使用DataOutputStream & DataInputStream代替ObjectStreams

這段代碼將變成這樣

try
    {
        address = InetAddress.getLocalHost();
        serverSocket = new ServerSocket(6000);
        System.out.println("server waits for players");

        while ( true){ 
             Socket socket = serverSocket.accept();
             Player playerWhite = new Player(socket);
             sendTestMessage(socket);// Move this method to Player thread and change the signature of this method accordingly to accept a socket
        }

    } 
    catch (IOException ex) 
    {
        Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
    }    

播放器

Player(Socket socket) throws IOException
{
    this.socket = socket;
    start();
}

請看這個聊天示例,以更好地理解。

是的,是的。

如果將其放入如下的endlees循環中,則應該可以正常工作:

    try
{
    while(true){
        address = InetAddress.getLocalHost();
        serverSocket = new ServerSocket(6000);
        playerWhite = new Player();

        System.out.println("server waits for players");
        playerWhite.socket = serverSocket.accept();
        playerWhite.start();
        sendTestMessage(playerWhite);
    }

} 
catch (IOException ex) 
{
    Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}  

但是我不建議將其放在線程中。 相反,我會將一個新客戶端的連接放在一個線程中,以便多個客戶端可以連接到服務器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM