如何在Java Server Client

时间:2015-12-02 23:49:34

标签: java sockets parameter-passing serversocket

我是Java Sockets的新手,我看过很多例子,但我无法理解如何将一个参数从服务器传递给客户端,反之亦然。我的目标是传递一个Object,这就是我使用Object I / O Stream的原因。

我必须上课服务器和播放器。

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

玩家类:

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

3 个答案:

答案 0 :(得分:1)

我会建议做这个公开的void 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 :(得分:1)

建议的更改。

  1. 仅创建一次ServerSocket。如果你已经完成了,你就不会得到" Address already in use"误差

  2. 创建服务器套接字后,您的线程应该在while (true)循环中以接受来自客户端的连接。

  3. 创建客户端套接字后,将该套接字传递给线程。

  4. 现在,Player用于从服务器向客户端套接字发送通信。所以你还需要一个像PlayerClient这样的类来创建服务器IP和端口的套接字。现在,PlayerClient应该再创建一个线程来处理IO操作,就像从服务器那样。在这种情况下,创建套接字不在客户端的while循环中。它创建一个服务器套接字一次。现在,您可以从多台计算机上运行此PlayerClient程序。

  5. 如果您只是发送原始类型,请使用DataOutputStream & DataInputStream而不是ObjectStreams

  6. 此代码将变为此

    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.java

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

    请查看此chat示例,以便更好地理解。

答案 2 :(得分:0)

是的。

如果你把它放在像这样的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);
}  

但我不建议把它放在一个帖子里。相反,我会将新客户端的连接放在一个线程中,这样多个客户端就可以连接到服务器