Многопользовательская игра на Java. Подключить клиента (игрока) к игре, созданной другим клиентом
Я работаю над многопользовательской игрой и не могу узнать, как подключить других клиентов к созданной игре. Я имею в виду, что клиент A создает сокет-соединение с сервером, и как другие клиенты (A,B...) могут подключаться к клиенту A? Может кто-нибудь помочь мне, пожалуйста?
PS Я новичок в сетевом программировании, так что если вы можете привести какой-то пример, я был бы очень признателен.
2 ответа
Другой клиент не может быть подключен к клиенту A из-за его брандмауэра.
Вы можете создать две основные сети:
Сервер-Клиент
Пиринговый
Но клиент может сохранить некоторые данные на сервере, и сервер может отправить их всем клиентам (вам не нужна одноранговая сеть, чтобы позволить клиенту B отправлять некоторые данные клиенту A).
Пример: Клиент B отправляет свою позицию на карте на сервер, сервер отправляет данные всем клиентам, поэтому Клиент A может нарисовать набор символов в позиции Клиента B.
Чтобы соединить два ПК вместе, вам необходимо перенаправить порт с модема вашего сервера на ПК, используемый в качестве сервера, и открыть порт из брандмауэра ПК, используемого в качестве сервера.
Вы также можете посмотреть здесь Создание многопользовательской игры на python. Я привел пример, где клиенты могли соединять их вместе с IRC и играть в игру Tic-Tac-Toe (чтобы вам не нужно было управлять сервером).). Я добавил пример в 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)
{
}
}
}
}
Я не могу дать вам пример для одноранговой сети, потому что я никогда не делал этого. Это действительно сложно, и вы должны сделать много исследований в Интернете.
Больше информации:
https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html
Вам нужен многопоточный сервер для обработки множества различных соединений.
Подсказка - я уже отвечал на некоторые похожие вопросы. Даже если язык программирования иногда отличается, я даю вам ссылку, логика всегда одна и та же, поэтому она может вам помочь:
Вот один из способов справиться с этим. Когда игрок хочет создать игру, его копия приложения должна открыть ServerSocket на известном порту - номер порта, который знает приложение - и, возможно, отобразить игроку IP-адрес, на котором был открыт сокет.
Затем, когда другой игрок хочет присоединиться к игре, он должен ввести тот же IP-адрес, и его копия приложения должна подключиться с использованием обычного клиентского сокета, введенного IP-адреса и известного порта, который знает приложение.
Проверьте javadoc Socket и ServerSocket для деталей.