[英]How to use existing Objects in an overwritten run() Method?
I'm a beginner in programming and do strugle a bit.我是编程初学者,有点挣扎。 So I'm building a TCP peer to peer Chat and that requires me to divide the tasks -> Threads.
所以我正在构建一个 TCP 点对点聊天,这需要我划分任务-> 线程。 So I want to built a Thread for the "writing" part of that connection (Scanner, DataOutputStream etc.) In order to do that i implemented Runnable and that forces me to write my Thread in the overwritten run() method.
因此,我想为该连接的“写入”部分(扫描仪、DataOutputStream 等)构建一个线程。为了做到这一点,我实现了 Runnable,这迫使我在覆盖的 run() 方法中写入我的线程。 Now I have a bit of a problem, because in Order to send my messages out to the "other end (another client) I need the "socket.getOutputStream" but I cant use it in the run() method and i dont know how to fix this problem, sitting already a week on this problem. Any ideas?
现在我有一点问题,因为为了将我的消息发送到“另一端(另一个客户端)我需要“socket.getOutputStream”但我不能在 run() 方法中使用它而且我不知道如何解决这个问题,已经坐了一个星期了。有什么想法吗?
public class ClientHorcher implements Runnable {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(11111);
System.out.println("Waiting For Connection:-");
Socket socket = serverSocket.accept();
Scanner scanner = new Scanner(System.in);
DataInputStream datenRein = new DataInputStream(socket.getInputStream());
DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream());
String nickname;
System.out.print("Gib einen Nickname ein: ");
nickname = scanner.nextLine();
while (true) {
String vonMsg = datenRein.readUTF(in);
System.out.println("Client:-" + vonMsg);
if (vonMsg.equals("exit")) {
System.out.println("Beenden!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
serverSocket.close();
System.exit(0);
}
System.out.print(nickname + ":-");
String zuMsg = scanner.nextLine();
datenRaus.writeUTF(zuMsg);
if (zuMsg.equals("exit")) {
System.out.println("Quiting!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
serverSocket.close();
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
}
}`
`public class ClientVerbinder implements Runnable {
public static void main(String[] args) {
try {
Socket socket = new Socket("Localhost", 11111);
System.out.println("Connected");
Scanner scanner = new Scanner(System.in);
DataInputStream datenRein = new DataInputStream(socket.getInputStream());
DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream());
String nickname;
System.out.print("Gib einen Nickname ein: ");
nickname = scanner.nextLine();
while (true) {
System.out.print(nickname+":-");
String zuMsg = scanner.nextLine();
datenRaus.writeUTF(zuMsg);
if (zuMsg.equals("exit")) {
System.out.println("Beenden!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
System.exit(0);
}
String vonMsg = datenRein.readUTF();
System.out.println("CLient"+":-" + vonMsg);
if (vonMsg.equals("exit")) {
System.out.println("Quiting!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
System.exit(0);
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
}
}
Multiple possibilities.多种可能性。
Use static variables.使用 static 变量。 Normally you would not do that, but because your code is all-static, you could
通常你不会那样做,但是因为你的代码是全静态的,你可以
Use member variables in an OO-style code.在 OO 风格的代码中使用成员变量。
If you wanted to do it properly, you'd split the server into two parts:如果你想正确地做到这一点,你可以将服务器分成两部分:
Socket connectionToClient = ss.accept
), and whenever a connection comes in, creates a new Socket connectionToClient = ss.accept
),每当有连接进来时,都会创建一个新的This way, the ClientHandler has all the data it needs (again as member variables) and can work on its own concerns (aka 'separation of concerns).这样,ClientHandler 拥有它需要的所有数据(同样作为成员变量)并且可以处理它自己的关注点(又名“关注点分离”)。
This is what I created.这就是我创造的。 Really simple.
真的很简单。
Classes:课程:
SimpleServer简单服务器
package stackoverflow.simplemtserver;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingDeque;
public class SimpleServer { // make it closeable and close sockets if this is not standalone
public static void main(final String[] args) throws IOException {
final int port = 7623;
new SimpleServer(port);
}
final LinkedBlockingDeque<SimpleServerClientHandler> clientHandlers = new LinkedBlockingDeque<>();
private final ServerSocket mServerSocket;
public SimpleServer(final int pPort) throws IOException {
mServerSocket = new ServerSocket(pPort);
final Thread m = new Thread(() -> runLoop(), getClass().getSimpleName() + " Main Loop");
m.start();
}
private void runLoop() {
while (true) {
try {
System.out.println("Server waiting for connection...");
@SuppressWarnings("resource") final Socket cs = mServerSocket.accept(); // do NOT close the socket here, no try-resource, will interrupt threaded communication!
final SimpleServerClientHandler ch = new SimpleServerClientHandler(this, cs);
clientHandlers.add(ch);
System.out.println("Connection accepted, handler started. Handlers active: " + clientHandlers.size());
} catch (final IOException e) {
// handle this how you need it
e.printStackTrace();
}
}
}
public void signOffClientHandler(final SimpleServerClientHandler pClientHandler) {
clientHandlers.remove(pClientHandler); // we could also accommplish this using stack trace to avoid access from outside, but this is the easier solution
}
public void spreadMessageToClients(final String pMessageFromClient, final SimpleServerClientHandler pSimpleServerClientHandler) {
for (final SimpleServerClientHandler ch : clientHandlers) {
if (ch != pSimpleServerClientHandler) ch.relayMessageToClient(pMessageFromClient); // we can work with identity == and != here
}
}
}
SimpleServerClientHandler SimpleServerClientHandler
package stackoverflow.simplemtserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class SimpleServerClientHandler {
private final SimpleServer mParentServer;
private final Socket mClientSocket;
private final DataInputStream mDIS;
private final DataOutputStream mDOS;
public SimpleServerClientHandler(final SimpleServer pSimpleServer, final Socket pCS) throws IOException {
mParentServer = pSimpleServer;
mClientSocket = pCS;
mDIS = new DataInputStream(mClientSocket.getInputStream());
mDOS = new DataOutputStream(mClientSocket.getOutputStream());
final Thread t = new Thread(() -> runComms(), getClass().getSimpleName() + " Comms Loop");
t.setDaemon(true); // threads now stop once server stops. this is NOT a soft exit
t.start();
}
private void runComms() {
try {
try {
while (true) {
// do all your logic here, work with DIS and DOS
final String messageFromClient = mDIS.readUTF();
if (messageFromClient == null) break;
if (!messageFromClient.startsWith("*")) mParentServer.spreadMessageToClients(messageFromClient, this);
}
} catch (final Exception e) {
// TODO: handle exception
}
} finally {
try {
mClientSocket.close(); // also closes DataIn/Out
} catch (final IOException e) { /* ignore */ }
mParentServer.signOffClientHandler(this);
}
}
public void relayMessageToClient(final String pMessageFromClient) {
try {
mDOS.writeUTF("*" + pMessageFromClient);
} catch (final IOException e) {
// ignore unless needed otherwise
}
}
}
SimpleClient简单客户端
package stackoverflow.simplemtserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
public class SimpleClient {
public static void main(final String[] args) throws UnknownHostException, IOException {
final String hostname = "localhost";
final int port = 7623;
try (final Socket s = new Socket(hostname, port);
final DataInputStream dis = new DataInputStream(s.getInputStream());
final DataOutputStream dos = new DataOutputStream(s.getOutputStream());
final Scanner scanner = new Scanner(System.in);) {
final Thread t = new Thread(() -> runListenerLoop(dis), SimpleClient.class.getSimpleName() + " Reader Thread");
t.setDaemon(true);
t.start();
while (true) {
System.out.println("Enter message:");
System.out.flush();
final String msg = scanner.nextLine();
if (msg == null) break;
System.out.println("Spreading message: " + msg);
dos.writeUTF(msg);
}
}
}
private static void runListenerLoop(final DataInputStream pDis) {
while (true) {
try {
System.out.println("Waiting for incoming messages...");
final String msg = pDis.readUTF();
System.out.println("Received: " + msg);
} catch (final SocketException e) {
// if ("java.net.SocketException: Connection reset".equals(e.getMessage()))
break;
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
From here on, there's now more ways you can extend this client/server communication:从这里开始,现在有更多方法可以扩展此客户端/服务器通信:
The pure peer-to-peer solution is this one.纯粹的点对点解决方案就是这个。
Example:例子:
p2p code:点对点代码:
package stackoverflow.simplemtserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
public class SimplePeerToPeerClient {
static public final int DEFAULT_PORT = 7642;
public static void main(final String[] args) throws UnknownHostException, IOException {
if (args.length == 0) {
System.out.println("Waiting on default port " + DEFAULT_PORT);
waitForConnection(DEFAULT_PORT);
} else if (args.length == 1) {
final int port = Integer.parseInt(args[0]);
System.out.println("Waiting on port " + port);
waitForConnection(port);
} else if (args.length == 2) {
final String hostName = args[0];
final int port = Integer.parseInt(args[1]);
System.out.println("Connecting to " + hostName + " on port " + port);
connectToOtherSide(hostName, port);
} else throw new IllegalArgumentException("Invalid amount of argument! Need none (listen) or 2: [hostname] [port] (connect)");
}
private static void waitForConnection(final int pPort) throws IOException {
try (final ServerSocket ss = new ServerSocket(pPort);) {
@SuppressWarnings("resource") final Socket socket = ss.accept(); // will get closed later
startComms(socket);
} // closes ServerSocket after 1st connection
}
private static void connectToOtherSide(final String pHostName, final int pPort) throws UnknownHostException, IOException {
@SuppressWarnings("resource") final Socket socket = new Socket(pHostName, pPort); // will get closed later
startComms(socket);
}
private static void startComms(final Socket pSocket) throws IOException {
try (
final DataInputStream dis = new DataInputStream(pSocket.getInputStream());
final DataOutputStream dos = new DataOutputStream(pSocket.getOutputStream());
final Scanner scanner = new Scanner(System.in);) {
// run the listener loop
final Thread t = new Thread(() -> runListenerLoop(dis), SimpleClient.class.getSimpleName() + " Reader Thread");
t.setDaemon(true);
t.start();
// run my keyboard-input-send loop
while (true) {
System.out.println("Enter message:");
System.out.flush();
final String msg = scanner.nextLine();
if (msg == null) break; // empty input ends client
System.out.println("Spreading message: " + msg);
dos.writeUTF(msg);
}
} finally {
try {
pSocket.close();
} catch (final IOException e) { /* ignore */ }
}
}
private static void runListenerLoop(final DataInputStream pDis) {
while (true) {
try {
System.out.println("Waiting for incoming messages...");
final String msg = pDis.readUTF();
System.out.println("Received: " + msg);
} catch (final SocketException e) {
// if ("java.net.SocketException: Connection reset".equals(e.getMessage()))
break;
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.