通过线程的多客户端服务器

时间:2013-02-12 17:45:16

标签: java networking tcp game-development

我遇到了一些麻烦,现在我已经看过这个教程了 http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html 本教程为您提供了一个服务器,多个客户端可以连接到服务器,当他们连接到服务器时,他们被告知与敲门工作一起,现在我了解如何传输数据和什么不是,但线程如何工作?

我正在开发一个网络乒乓球游戏,其中服务器将保持位置并将它们传递给客户端,现在我有一个客户端连接到服务器并且球位置传递给客户端,工作正常,有点跳跃,但我确定.sleep的线程会有所帮助。但无论如何我的问题是,我如何让我的客户成为一个线程?以及如何存储它们?

例如,这里是敲门服务器multiThread类

package knockKnockServer;

import java.net.*;
import java.io.*;

public class KKMultiServerThread extends Thread {
private Socket socket = null;

public KKMultiServerThread(Socket socket) {
super("KKMultiServerThread");
this.socket = socket;
}

public void run() {

try {
    PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
    BufferedReader in = new BufferedReader(
                new InputStreamReader(
                socket.getInputStream()));

    String inputLine, outputLine;
    KnockKnockProtocol kkp = new KnockKnockProtocol();
    outputLine = kkp.processInput(null);
    out.println(outputLine);

    while ((inputLine = in.readLine()) != null) {
    outputLine = kkp.processInput(inputLine);
    out.println(outputLine);
    if (outputLine.equals("Bye"))
        break;
    }
    out.close();
    in.close();
    socket.close();

} catch (IOException e) {
    e.printStackTrace();
}
}
}

在服务器中我们有

package knockKnockServer;

import java.net.*;
import java.io.*;

public class MultiKKServer {
public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = null;
    boolean listening = true;

    try {
        serverSocket = new ServerSocket(4444);
    } catch (IOException e) {
        System.err.println("Could not listen on port: 4444.");
        System.exit(-1);
    }

    while (listening)
    new KKMultiServerThread(serverSocket.accept()).start();

    serverSocket.close();
}
}

现在查看服务器,它将在每个连接上创建一个新的KKMultiServerThread,但我如何存储它们?我可以制作一个KKMultiServerThread数组吗? 我试图创建一个KKMultiServerThread数组 当我尝试这一行时

multi[0] = new KKMultiServerThread(serverSocket.accept()).start();

我收到此错误“无法将void转换为Thread” 如果有人能对我的问题有所了解,那就太棒了。

帆布

更新

我现在拥有自己的线程类

package Pong;

import java.net.*;
import java.io.*;

public class PongPlayerThread extends Thread 
{
private Socket socket = null;
private String pongData = "";

public PongPlayerThread(Socket socket, int id) 
{
    super("PongPlayerThread");
    this.socket = socket;
}

public void passData(String data)
{
    pongData = data;
}

public void run()
{
    try
    {
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        while(true)
        {
            out.println(pongData);
        }
    }
    catch (IOException e) 
    {
        e.printStackTrace();
    }
}

}

pongData是一个字符串,它将所有信息保存在一个字符串中,现在如果我在我的pong服务器顶部声明一个player1,那么

private static PongPlayerThread player1;

并在收听时执行此行

    while(listen)
    {
        PongPlayerThread player1 = new PongPlayerThread(serverSocket.accept(), 0).start();
    }

它给了我这个错误“无法从void转换为PongPlayerThread”我该怎么解决这个问题?

2 个答案:

答案 0 :(得分:0)

客户端何时连接到服务器。服务器通常会专门为该客户端创建一个新线程。这是一些伪代码:

WHILE SERVER IS RUNNING

SERVER WAITS FOR A CLIENT TO CONNECT
SERVER ACCEPTS THE CLIENT IF THERE IS ENOUGH MEMORY TO CREATE A NEW THREAD
SERVER CREATES A NEW THREAD ROUTINE FOR THE CLIENT PASSING THE CLIENT INFORMATION TO THE THREAD
SERVER CONTINUES TO LISTEN WHILE EACH THREAD IS SPECIFICALLY TAILORED FOR THE CLIENTS

REPEAT

你问过减少滞后需要哪些步骤?对于初学者来说,设置允许的最大连接数。您不希望5000个客户端拥有自己的线程。除非您的机器可以处理所有这些并仍然运行。使用UDP代替TCP,数据压缩尝试最小化带宽,不要一次发送50 GB的信息;如果您只需要发送几个字节的信息。尝试发送不是字符串但以字节为单位的位置信息。例如,您可以将位置X = 5Y = 0发送为50,并将第一个十进制数字解析为X,将第二个十进制数字解析为Y.

不是在线程例程中传递客户端套接字,而是为客户端传递唯一标识符。由于Pong是两个玩家限制与两个客户的连接。播放器1为0,播放器2为1.所以

new KKMultiServerThread(clientID).start(); // clientID is of type int

修改

int id = 0;
while(serverIsRunning)
{
    Client client = server.accept();
    if (id > 2) client.Close(); // Do not accept.
    Thread.New(id).Start();
    id++;
}

答案 1 :(得分:0)

您的数组声明缺少对象类型

KKMultiServerThread multi[0] = new KKMultiServerThread(serverSocket.accept()).start();

为什么要打扰?除非线程需要相互通信,否则让线程自由运行是可以的。就服务器而言,Run()方法定义套接字的整个生命周期。每个线程都有一个单独的游戏状态副本(只要你不使用静态),并且很乐意与客户进行通信而无需任何额外的干预。

这种情况下,Java中的Socket / Thread库对你有帮助,除非你有特殊需要,否则不要让它更复杂。