[解決済み] Javaで作られた多人数参加型ゲーム。他のクライアントが作成したゲームにクライアント(プレイヤー)を接続する。
質問事項
私は多人数参加型ゲームに取り組んでいますが、作成したゲームに他のクライアントを接続する方法を見つけることができません。つまり、クライアントAがサーバーにソケット接続を作成し、どのように他のクライアント(A、B...)がクライアントAに接続することができますか? どなたか教えてください。
追伸:私はネットワークプログラミングの初心者なので、もし何か例を添付していただけると大変ありがたいです。
どのように解決するのですか?
クライアントAのファイアウォールにより、別のクライアントが接続できない。
2種類のメジャーなネットワークを作成することができます。
-
サーバー・クライアント
-
ピアツーピア
しかし、クライアントがサーバーにデータを保存し、サーバーがすべてのクライアントにデータを送信することができます(クライアントBがクライアントAにデータを送信するために、Peer-to-Peerネットワークは必要ありません)。
例 クライアントBが自分のマップの位置をサーバーに送信し、サーバーがそのデータを全クライアントに送信することで、クライアントAはクライアントBの位置にキャラクターのタイルセットを描画することができます。
2台のPCを接続する場合、サーバーのモデムからサーバーとして使用するPCにポートを転送し、サーバーとして使用するPCのファイアウォールからポートを開放する必要があります。
こちらもご覧ください。 Pythonでマルチプレイヤーゲームを作成する この例では、IRCでクライアント同士をつないで、三目並べで遊ぶことができました(サーバーを管理する必要がない)。この記事の最後に、Javaでの例を追加しました。
簡単なサーバーの例です。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class Server
{
public static void main(String[] args) throws Exception
{
ServerSocket listener = new ServerSocket(4000);
String line;
try
{
while (true)
{
Socket socket = listener.accept();
BufferedReader readerChannel = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter writerChannel = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
try
{
writerChannel.write(new Date().toString() + "\n\r");
writerChannel.flush();
while ((line = readerChannel.readLine()) != null)
{
System.out.println(line);
}
}
finally
{
socket.close();
}
}
}
finally
{
listener.close();
}
}
}
簡単なクライアントの例です。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;
public class Client
{
public static void main(String[] args) throws Exception
{
Socket socket = new Socket("127.0.0.1", 4000);
BufferedWriter writerChannel = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader readerChannel = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
writerChannel.write(new Date().toString() + "\n\r");
writerChannel.flush();
while ((line = readerChannel.readLine()) != null)
{
System.out.println(line);
}
}
}
もご覧ください。
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class Client
{
public static void main(String[] args) throws Exception
{
SSLSocketFactory socketBuilder = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) socketBuilder.createSocket("127.0.0.1", 4000);
}
}
簡単なIRCの例です。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class Client
{
public static void main(String[] args) throws Exception
{
SSLSocketFactory socketBuilder = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) socketBuilder.createSocket("irc.freenode.net", 6697);
BufferedWriter writerChannel = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader readerChannel = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line, computerName, nick, login, channel = "#bot", channelPassword = "";
long id = 1;
computerName = java.net.InetAddress.getLocalHost().getHostName();
nick = computerName + "_" + id;
login = computerName + "_" + id;
writerChannel.write("NICK " + nick + "\r\n"); // Join IRC with a specific Nick
writerChannel.write("USER " + login + " 8 * :" + login + " \r\n"); // Join IRC with a specific User
writerChannel.flush();
while ((line = readerChannel.readLine()) != null)
{
if (line.indexOf("004") != -1) // If connected
{
break;
}
else if (line.indexOf("433") != -1) // If Nick already in use
{
id++;
nick = computerName + "_" + id;
login = computerName + "_" + id;
writerChannel.write("NICK " + nick + "\r\n");
writerChannel.write("USER " + login + " 8 * :" + login + " \r\n");
writerChannel.flush();
}
}
writerChannel.write("JOIN " + channel + " " + channelPassword + "\r\n"); // Join a channel
writerChannel.flush();
while ((line = readerChannel.readLine()) != null)
{
try
{
line = line.substring(line.indexOf("#"));
channel = line.substring(0, line.indexOf(" "));
if (line.toLowerCase().startsWith("ping")) // avoid ping time-out
{
writerChannel.write("PONG :" + line.substring(5) + "\r\n");
writerChannel.flush();
}
else if (line.toLowerCase().contains("!ping"))
{
writerChannel.write("PRIVMSG " + channel + " :pong\r\n");
writerChannel.flush();
}
else if (line.toLowerCase().contains("!join"))
{
String newChannel = line.substring(line.indexOf("!join") + 6);
int stringPosition;
if ((stringPosition = newChannel.indexOf(" ")) != -1)
{
String newPassword = newChannel.substring(stringPosition + 1);
newChannel = newChannel.substring(0, stringPosition);
writerChannel.write("JOIN " + newChannel + " " + newPassword + "\r\n");
writerChannel.flush();
}
else
{
writerChannel.write("JOIN " + newChannel + "\r\n");
writerChannel.flush();
}
}
else if (line.toLowerCase().contains("!leave"))
{
writerChannel.write("PART " + channel + "\r\n");
writerChannel.flush();
}
else if (line.toLowerCase().contains("!quit"))
{
writerChannel.write("QUIT\r\n");
writerChannel.flush();
System.exit(0);
}
}
catch (Exception e)
{
}
}
}
}
私はPeer-to-Peerネットワークはやったことがないので、例を挙げることはできません。これは本当に難しいことで、インターネットでたくさん調べなければならないのです。
その他の情報
-
https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html
-
多くの異なる接続を処理するために、マルチスレッドサーバーが必要です。
ヒント - 似たような質問にはすでに回答しています。たとえプログラミング言語が異なっていても、私はあなたにリンクを与えますが、ロジックは常に同じなので、おそらくあなたの助けになるでしょう。
関連
-
[解決済み】imageio.IIOException: 入力ファイルが読み込めない
-
[解決済み】javaで指定されたファイルが見つからない
-
[解決済み】Javaの".class期待値"
-
[解決済み】不正なエスケープ文字"㊧"について
-
[解決済み】「'void' type not allowed here」エラーの原因とは?
-
[解決済み】Java JDK - doubleからintへの非可逆変換の可能性
-
[解決済み】Eclipseがエラーメッセージ "Java was started but returned exit code = 1" を返す
-
[解決済み】Javaを包含するクラスではないのか?
-
[解決済み】Javaのswitch文。定数式が必要だが、定数である
-
[解決済み】Node.jsのエラーECONNRESETをデバッグするにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Hibernateエラー:同じ識別子値を持つ別のオブジェクトがすでにセッションに関連付けられました。
-
[解決済み】このコンパイルユニットは名前付きモジュールに関連しているため、名前付きパッケージeclipseを宣言する必要があります。
-
[解決済み】代入の左手は必ず変数 CharAt
-
[解決済み] java のクラス内のコンストラクタは、指定された型に適用できない
-
[解決済み】 java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver [重複]。
-
[解決済み] hibernate のプロパティが見つかりません。
-
[解決済み】Javaの部分文字列:「文字列のインデックスが範囲外」。
-
[解決済み】JLabelのテキストを中央に配置するには?
-
[解決済み】Javaでユーザー入力を待機させる方法
-
[解決済み】Eclipseで「公開型 <<classname>> は独自のファイルで定義する必要があります」エラー【重複あり