My two clients have to communicate directly with each other. Both of them has ServerSocket and Socket, too. I can demonstrate it with this code snippet:
final ServerSocket serverSocket = new ServerSocket(12345);
new Thread(new Runnable() {
#Override
public void run() {
try {
Socket clientSocket = serverSocket.accept();
System.out.println(clientSocket.getInputStream().read());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
Socket clientSocket = new Socket(InetAddress.getLocalHost(), 12345);
clientSocket.getOutputStream().write(1);
clientSocket.getOutputStream().flush();
It works OK, but i cannot test them, if they are on the same IP (for example on localhost), because the client will connect to itself. My question is, how can i test or rewrite this, to test two client connecting to each other on the same IP and port?
Make the port number configurable via a command line argument, property file or some other way. For the client side you'll need to provide port number of the other instance.
Related
SOLVED = my server code need to place in the right place. Outside EventQueue.Invokeletter{});
When I run the client and click button login, the client cannot connect to server.
The first time I use it, it's working, but for no reason my Client cannot connect to Server.
What should I do to make it right?
Server Code
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new mainmenu().setVisible(true);
ServerSocket ss=new ServerSocket(1234);
Socket socket1=ss.accept();
} catch (IOException ex) {
Logger.getLogger(mainmenu.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
Client Code
private void btnLoginActionPerformed(java.awt.event.ActionEvent evt) {
try {
Socket cs = new Socket("localhost", 1234);
} catch (IOException ex) {
Logger.getLogger(mainclient.class.getName()).log(Level.SEVERE, null, ex);
}
}
Here:
ServerSocket ss=new ServerSocket(1234);
Socket socket1=ss.accept();
That waits for one client to connect. Then your run() method deals with that client ... and ends!
If you want your code to wait again, you need to put a loop around that part of your code.
In other words: you wrote code that will open a server socket, wait for an incoming connection, handle that, and then ... fade away. If you want to serve more than one client over time, that "fade away" part needs to be replaced with a loop that keeps waiting for new clients, as long as the "server" program is up and running.
I've written a basic TCP chat in Java and when testing locally (i.e. localhost) it's been working fine. I can connect, type messages to myself and receive without issues. I can connect and disconnect several times a second.
However, when trying to connect through my router's external IP for whatever reason it hangs when trying to initialize the ObjectInputStream on not only the Client side, but also Server side. So I'm guessing it's something to do with my Router firewall, on which I added a firewall rule. I did only create a firewall rule for the specific port 1777 where I make my connection, is it possible that the data sent when flushing ObjectOutputStream is sent on another port? Which wouldn't make sense I guess considering the socket is bound to a specific port.
I am flushing after initializing the ObjectOutputStream and I am creating that before creating the ObjectInputStream, on both sides. What doesn't make sense to me is that it allows for a connection to be made.
I guess code may be irrelevant in this case, but here it is anyway:
This Thread is run at all times, and waits for connections then starts a new Thread for handling the connecting client:
public void run() {
while (connected) {
try (ServerSocket serverSocket = new ServerSocket(port)) {
Socket socket = serverSocket.accept();
new ClientHandler(socket);
} catch (IOException e) {
...
}
}
}
Constructor of ClientHandler class:
public ClientHandler(Socket socket) throws IOException {
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.flush();
inputStream = new ObjectInputStream(socket.getInputStream());
welcomeClient();
start(); // Start listening for messages.
}
This is where the ClientHandler Thread hangs.
Here is Client side code:
// Get IP, port and stuff
socket = new Socket(ip, port);
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.flush();
inputStream = new ObjectInputStream(socket.getInputStream());
// Write a couple objects and read some objects.
They both hang on "inputStream = new ObjectInputStream(socket.getInputStream());"
What could be the problem? I can also connect through my local IP, which makes me think it's still an outbound->inbound firewall issue for whatever reason.
am currently working on a project where I have to build a multi thread server. I only started to work with threads so please understand me.
So far I have a class that implements the Runnable object, bellow you can see the code I have for the run method provided by the Runnable object.
public void run() {
while(true) {
try {
clientSocket = serversocket.accept();
for (int i = 0; i < 100; i++) {
DataOutputStream respond = new DataOutputStream(clientSocket.getOutputStream());
respond.writeUTF("Hello World! " + i);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
//
}
}
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
}
Bellow is the main method that creates a new object of the server class and creates a threat. initializing the Thread.
public static void main(String args[]) {
new Thread(new Server(1234, "", false)).start();
}
I know this creates a new thread but it does not serve multiple clients at once. The first client need to close the connection for the second to be served. How can I make a multi threated server that will serve different client sockets at once? Do I create the thread on the clientSocket = serverSocket.accept();
yes.
from the docs:
Supporting Multiple Clients
To keep the KnockKnockServer example simple, we designed it to listen for and handle a single connection request. However, multiple client requests can come into the same port and, consequently, into the same ServerSocket. Client connection requests are queued at the port, so the server must accept the connections sequentially. However, the server can service them simultaneously through the use of threads—one thread per each client connection.
The basic flow of logic in such a server is this:
while (true) {
accept a connection;
create a thread to deal with the client;
}
The thread reads from and writes to the client connection as necessary.
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html
So, I have the following code that catches a new connection, then hands that connection to its own thread to handle the client.
private void loop(int port) {
// Opens a port for connections.
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Server running in port " + port);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// Listens for a connection
while (onlineState == true && serverSocket != null) {
Socket clientSocket = new Socket();
try {
clientSocket = serverSocket.accept();
System.out.println(clientSocket.getInetAddress() + " has connected to the port " + clientSocket.getPort());
new Thread(new SocketThread(clientSocket)).run();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
So, my problem here is that when I try to connect with multiple client apps to the server, the server only seems to either accept one connection at any given time. The client itself is a very simple application of the basic tutorial: it simply repeats any string that the server sends to it.
I have two guesses as to why this is happening: a) there's something wrong with my handling code, b) it's because both connections are from the same IP.
However, neither case is a good thing. Any ideas what I'm doing wrong? (Except everything)
Two things:
You want to call start(), not run() on your Thread object. The difference is that start() actually goes and does threaded stuff, like running it in the background. Calling run() from where you call it there will handle all the client communication right there, inline. That's why you only ever accept one connection - you won't accept any more until you've serviced that client.
You don't want to call clientSocket.close() in your main thread. In your implementation of SocketThread, call clientSocket.close() at the end of your run() method, probably inside a finally block.
Also, does SocketThread extend Thread? If so, you don't need new Thread(), just do
new SocketThread(clientSocket).start();
If it doesn't extend Thread, why not name it SocketRunnable or ClientRunnable or something like that.
I'm building something here and I found myself in a pickle. Just some introduction first. I'm developing a client-server game. One of the functions it has is a chat that players can use to talk to another.
Player1 send a message to the server and the server forwards it to the respective Player2. My problemas is: how can I access classes from another thread so I can get the Socket object to relay the message to Player2.
while (listening)
{
try
{
//this is how I start a thread for each connection
//do I need to use identifiers or something?
new Client(serverSocket.accept()).start();
}
catch(IOException A)
{
reportError(A.toString()); //reportError is a function of mine
}
}
there are many ways to achieve this, the easiest would be:
public void start(){
try {
ServerSocket ss = new ServerSocket(port);
System.out.println("Starting server on port: " + port);
while (serverState) {
Socket socket = ss.accept();
//stop server
if (!serverState) {
break;
}
Client handler = new Client(this, socket);
handler.start();
}
//when server is stopped, close all connections
for (Client client : clients.values()) {
client.closeConnection();
}
} catch (IOException e) {
}
}
if you send "this" inside the constructor of client and set it as a private variable you could Access it from the run function(other thread)