i have this TCP socket (i only posted relevant parts and removed exception throwings):
static Socket clientSocket;
static BufferedReader inFromServer;
The connection part (i call it from another class):
static Socket clientSocket = new Socket(ip, port);
static BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
And to recieve text i have a runnable thread wich i call like this:
public static void StartRecievingText(){
TCPScanner.setReader(inFromServer);
Thread t1 = new Thread(new TCPScanner());
t1.start();
}
The thread:
public class TCPScanner implements Runnable {
static BufferedReader inFromServer;
public static void setReader(BufferedReader reader){
inFromServer = reader;
}
public void run() {
while (true) {
String temp = inFromServer.readLine();
System.out.println(temp);
}
}
}
The thread runs to the inFromServer.readline() part and appears to recieve nothing.
It's my first time working with threads and ...well second time working with tcp connections so i don't know if i've done anything wrong.
Thanks for your help (and sorry for spelling mistakes... still learning english)
Your client is reading lines but you aren't sending lines, so the client blocks forever waiting for a line terminator that never arrives. Either add a newline to what is being sent, or use another read method that doesn't require it.
There are other problems with your code. None of these data items should be static. Your read loop should test the result of readLine() for null, and close the socket and exit if true.
Related
First question here on StackOverflow, so please excuse me if I ask this incorrectly.
Basically, I'm writing a Multicast Client that indefinitely listens to a multicast address until the user types "quit" into the console. I've found that setting SO_TIMEOUT for the MulticastSocket, checking if "quit" has been typed, and then returning to the receive method call doesn't really work since a packet could be sent right after the timeout and the check of the console blocks. So I believe the best option is to simply have 2 threads going where one listens on the socket and blocks until it receives something, and the other thread listens to the console until told to quit. The only issue I have is that I'm unsure of how to go about having the console listening thread tell the socket thread to close the socket and terminate. System.end() would work but I fear that I'd leave a socket open, etc.
TLDR; Is there a way for the main method of a class to start a thread, and then respond a specific way once that thread ends? I need to listen to the console on one thread and a MulticastSocket on another, or just in the main of the client class.
Thanks everyone.
I would call Socket.close() to close the socket. This will produce an IOException in that thread. so before doing this I would set a flag like closed = true; and have the other thread check this before printing the error i.e. don't print an IOException if you have been closed. Something like this.
public class SocketListener implements Runnable, Closeable {
final MulticastSocket socket;
final Consumer<DatagramPacket> packetConsumer;
volatile boolean closed;
public SocketListener(MulticastSocket socket, Consumer<DatagramPacket> packetConsumer) {
this.socket = socket;
this.packetConsumer = packetConsumer;
}
#Override
public void run() {
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
try {
while(!closed) {
socket.receive(packet);
packetConsumer.accept(packet);
}
} catch (IOException e) {
if (!closed)
e.printStackTrace();
}
}
#Override
public void close() throws IOException {
closed = true;
socket.close();
}
}
for example, in your main thread you can do
MulticastSocket socket = ...
Consumer<DatagramPacket> packetConsumer = ...
try (SocketListener listener = new SocketListener(socket, packetConsumer)) {
boolean finished = false;
do {
// read from the console
if (some condition)
finished = true;
} while(!finished);
} // calls close() for you.
I have to do a cluedo game for Uni, so we have a Server class and Clients that are connecting. For each Client connecting we want to start a own ServerThread with the socket of the Client that is connecting. This Thread just listens to incoming messages and tells the server class to send them back to the client(s).
PROBLEM: each time a new client connects he is overwriting this ServerThread so there is always just one ServerThread and we would like to have one for each Client. We send JSON messages between the Clients and right now the receive message in the ServerThread reads only from the last connected socket. How can i solve this? i added my accept method in the Server i guess the mistake is there but could be anywhere. Thanks for your help!
Mauritius
Server
public void accept() throws IOException{
while(true){
Socket socket = serverSocket.accept();
Runnable r = new ServerThreadHandler(socket);
Thread t = new Thread(r);
t.start();
}
}
ServerThreadHandler:
public class ServerThreadHandler implements Runnable {
static Socket socket=null;
protected User client;
//private static int i;
private static BufferedReader in;
private static OutputStreamWriter out;
public void createUser(String nick, String group, String[] ext) throws IOException{
client = new User(nick, group, ext, null, false, 0, false, socket, socket.getPort());
}
/**
* constructor-Method
* #param socketS
*/
ServerThreadHandler(Socket socketS){
socket = socketS;
}
public void run(){
Server.setThreadList(socket);
in = createReader();
out = createWriter();
//and so on...
}
}
The logic mentioned in you code snippet will definitely create as many threads as the no. of clients that are connecting.
However, the possible reason might be, since the Socket variable in ServerThreadHandler is Static, all subsequent threads being created overwrite the same socket variable causing issue in the previously created thread which is using the socket variable.
You should consider, using non static variable for the Socket in ServerThreadHandler since any runnable class should hold a state and should not be using a static socket.
From what I understood from your question,
createUser method is an instance method of ServerThreadHandler. Hence you must have created the instance of ServerThreadHandler to invoke createUser from another class. Hence you can access the socket variable even if it is an instance variable.
Unfortunately the code has many design flaws:
The quickest fix I can suggest is to remove User class and move everything in the Handler class (or vice verca ? )
also make all your variable non-static
static Socket socket=null;
protected User client;
//private static int i;
private static BufferedReader in;
private static OutputStreamWriter out;
they should be :
Socket socket=null;
protected User client;
//private int i;
private BufferedReader in;
private OutputStreamWriter out;
The Socket member variable should be non-static. Ditto the reader and writer.
Never make a variable static unless you have a really good reason to do so and understand the consequences.
I am trying to make a chat server (as a smaller part of a game I'm coding) that accepts two clients. The way I have done this so far is by creating two completely different sets of a Socket, ObjectInputStream, and ObjectOutput stream.
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private ObjectOutputStream output2;
private ObjectInputStream input2;
private ServerSocket server;
private Socket connection;
private Socket connection2;
static final int PORT = 6789;
The outputting is working just fine, but the input method is not working as planned. This is the input method:
//runs while conversation is active
private void whileChatting() throws IOException{
waitForConnection();
setupStreams();
String message = " You are now connected! ";
sendMessage(message);
ableToType(true);
do{
message = input.readUTF();
showMessage("\n" + message);
message = input2.readUTF();
showMessage("\n" + message);
}while(!message.contains("END"));
}
The line message = input.readUTF(); is waiting for there to be something to read. Is there a way to check if there is something to read and only set message equal to it if not null? No, if(input.readUTF() != null) does not work. Alternatively, I think there would be a way to do this with multiple threads, but I do not have a good grasp on how threads work, so if someone could give me an example, that would be very helpful.
Thanks.
readUTF() is considered a blocking call, which means when it is called, it will hold up the thread until it returns a value. Even if you were to nullcheck, it will still block your thread from continuing until something came through the stream (whether it be a string or a null).
To handle something like a multithreaded connection:
Create a class that implements Runnable
class User implements Runnable {
}
In that class, add you in\out stream. Make sure they're aren't static so they're instance variables. You are gonna want a new in/out stream for each connection
class User implements Runnable {
DataOutputStream out;
DataInputStream in;
Socket socket;
public User(Socket s) {
socket = s;
}
public void run() {
try {
out = new DataOutputStream(socket.getOutputStream());
//same with inputstream
String input;
while(!(input = in.readUTF()).equals("END")) {
//do something with input
}
}
}
}
When your server accepts a connection...
public static void main(String[] args) {
ExecutorService executors = Executors.newCachedThreadPool(); //contains your threads
ServerSocket ss;
while(true)
executor.execute(new User(ss.accept()));
}
ServerSocket.accept() is also a blocking call, which means the loop it's being called in will block (wait) until a user is accepted. This is called Blocking-IO.
All read calls from java.io are blocking.
DataInputStream.readUTF
DataInputStream.readInt
ObjectInputStream.readObject
If you want a system where methods such as these don't block, I suggest looking into the java.nio package (new IO). It far more advanced in my opinion, especially for someone who doesn't have a grasp on basic networking yet, but non-blocking IO's allow for your underlying OS to inform your application when to read/write (through a selector), thus removing the need for blocking calls.
Other than that, there is no way you can prevent readUTF to stop blocking, or somehow skip it without data coming through it.
I'm trying to develop a java chat server using thread pool, but i don't know how to handle incoming message from clients. i've think to save every socket connection in a hashmap and add the task to the queue of thread pool.. but how the server can know when he's receveing a message from a client without instantiate a bufferedreader?
You dont need to initialize a buffered reader for each one of your sockets. You can look through and check if there is data waiting to be read.
for(Socket socket : socketsList)
if(socket.getInputStream().available() > 0) {
// you have data to be read from this socket
}
Your server will need to use agent objects that hold a BufferedReader that reads from their socket. Perhaps you will need to create a collection of these agent objects.
For example,
class ServerAgent implements Runnable {
private OutputStream out;
private BufferedReader br;
public ServerAgent(Socket clientSocket) throws IOException {
out = clientSocket.getOutputStream();
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// ....
}
#Override
public void run() {
// TODO finish code that reads from br, BufferedReader
}
}
And your Server could have code like:
while (true) {
Socket clientSocket = server.accept();
futureList.add(threadPoolExector.submit(new ServerAgent(clientSocket)));
}
Can anyone give me insight into why the ServerSocket constructor never returns in the new thread? (I never see the "Opened" message printed to the console.) It seems the main thread prevents the server socket thread from running by entering into readLine too quickly:
public class Main
{
public static void main(String[] args) throws IOException
{
new Thread(new SocketOpener()).start();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inLine = br.readLine();
System.out.println(inLine);
}
}
public class SocketOpener implements Runnable
{
public void run()
{
try
{
System.out.println("Opening...");
ServerSocket socket = new ServerSocket(4444);
System.out.println("Opened");
}
catch (IOException ex)
{
System.out.println("IO Error");
}
}
}
I don't think that it's the ServerSocket constructor that blocks, but the System.out.println("Opened"). The fact that the main thread is trying to read from System.in prevents outputs to be done on System.out.
Reading from System.in causes a lot of problems:
Under some circumstances you can't:
Create a Temp-File (because of 2)
Read the Inet4Adress of your maschine
Load a DLL
I've encountert some of this Problems with Windows Server 2003 and older. This happens because of some Bugs in the Win32-API ans Java-VM.
But there may be an easy workarround:
Only call System.in.read(), if System.in.availiable() returns a value larger than 0.
Deadlock between
System.loadLibrary() and
System.in.read()
Inet4AddressImpl.getLocalHostName is
hanging intermittenly
Deadlock
in Win32