I'm trying to create a game using only two classes - ServerSocket and Socket. Everything must be at the TCP (not UDP), while architecture is necessarily P2P. The way this game works is that one player chooses a number, then the other and it starts with one of them (no matter which one) counting down. I came across a problem. I establish a connection between two clients and both may enter the selected number. I do not know why I can not send this number to another client. Is the problem that Socket can not send and receive messages at the same time? I've read that there is a possibility to do this using two separate Threads (one receives data, the other sends), but I do not know how exactly.
#Override
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(System. in ));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
System.out.println("PICK A NUMBER:");
while (!br.ready()) {
Thread.sleep(500);
}
Integer numberGamePicked = Integer.parseInt(br.readLine());
Thread.sleep(500);
out.println(numberGamePicked);
Thread.sleep(1000);
BufferedReader in =new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int whatOpponentSend = Integer.parseInt( in .readLine());
System.out.println("RECEIVED " + whatOpponentSend);
}
Of course, up to this point everything is in the run() method. Is the problem that both of them execute the same code at the same time?
Related
I've been making a chat room where multiple clients can connect and talk together on the same server. The only problem I'm having is getting each client to send more than one message. I've been trying different ways of looping the method to do so but I'm having some issues.
Any help would be appreciated :) thank you.
HERE'S THE CODE:
public class Client {
public static void main(String[] args){
Scanner clientInput = new Scanner(System.in);
try {
Socket SOCK = new Socket("localhost", 14001);
System.out.println("Client started!");
//Streams
while(true){
OutputStream OUT = SOCK.getOutputStream(); //writing data to a destination
PrintWriter WRITE = new PrintWriter(OUT); // PrintWriter prints formatted representations of objects to a text-output stream
InputStream in = SOCK.getInputStream(); //reads data from a source
BufferedReader READ = new BufferedReader(new InputStreamReader(in));
//---------------------------------
System.out.print("My input: ");
String atServer = clientInput.nextLine();
WRITE.write(atServer + "\n");
WRITE.flush(); //flushes the stream
String stream = null;
while((stream = READ.readLine()) != null){ //if stream is not empty
System.out.println("Client said: " + stream);
}
READ.close();
WRITE.close();
}
} catch (UnknownHostException e){
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
I've tried using a while loop to continuously ask for an input but doesn't seem to be working.
Are you making it out of the READ.readLine() while loop? Perhaps you're never getting an end of input character and thats never terminating. Also, you're closing both your READ and WRITE at the end of the while loop, and then expect them to be open on the next iteration. Move those and the close statements to the same layer as the Socket.
With that, every time you send something, your client is expecting something in response from the server. If you don't want them to be dependent on each other, I recommend moving the receive logic to its own thread in a while(true) loop.
I'm learning distributed systems basics and currently I'm trying to do a simple yet realistic messenger between one server and one client. What I do intend is that on each endpoint socket side (Server and Client) text automatically updates (like a real "messaging app"). In other words, I want that the moment I write and "send" the message, it automatically appears on recipient side. What I have now follows this schema:
I send a message (let's assume from client)
To see that message on Server's side I need to reply first (because Server's BufferedReader / Client's PrintWriter is only read after asking for the answer)
My code:
public class ClientSide {
public static void main(String [] args){
String host_name = args[0];
int port_number = Integer.parseInt(args[1]);
try {
Socket s = new Socket(host_name, port_number);
PrintWriter out =
new PrintWriter(s.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(s.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null) {
out.println(answer);
System.out.println("\nlocalhost said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ClientSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class ServerSide {
public static void main(String [] args){
int port_number = Integer.parseInt(args[0]);
try {
ServerSocket ss = new ServerSocket(port_number);
Socket tcp = ss.accept();
PrintWriter out =
new PrintWriter(tcp.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(tcp.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String answer;
while ((answer = stdIn.readLine()) != null){
out.println(answer);
System.out.println("\nClient said\n\t" + in.readLine());
}
} catch (IOException ex) {
Logger.getLogger(ServerSide.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
How can I do this? Does it involve advanced knowledge on the matter?
Thanks in advance.
The core problem is that you want to wait for two events concurrently -- either a message from the socket, or input from the user!
You want to wait on both at the same time -- you don't want to be stuck waiting for a message in the socket if the user types a message; nor to be waiting for the user message while you have a new message from the network.
To 'wait' for messages from multiple streams, you have java.nio. I believe it is the most correct way of doing it.
But if you want to keep using the BufferedReader, there is a ready() method that returns true if and only if there is a message waiting to be read.
Your code after the in and stdIn declarations would then look something like (I didn't test it!!):
while(true) {
if(stdIn.ready()) {
System.out.println("I said " + stdIn.readLine());
}
if(in.ready()) (
System.out.println("He said " + in.readLine());
}
}
A few somewhat useful random links:
Java - Reading from a buffered reader (from a socket) is pausing the thread
Is there epoll equivalent in Java?
Saying my requirement is:
Either user type something in console (from system.in) or socket receive something, proceed to next step.
So I have a scanner
Scanner sc = new Scanner(System.in);
Have an Udp client. (a different input source)
DatagramSocket clientSocket = new DatagramSocket();
My code is
while (true) {
if (sc.hasNext()) {
String str = sc.next();
proceed(str)
} else {
clientSocket.receive(pack);
proceed(pack)
}
}
Obviously this code will not work. Because when checking sc.hasNext(), java is waiting user to type some input in console. Currently what I can do is open an thread for Udp client. If I change the order,
while (true) {
clientSocket.receive(pack);
if (not receive) read from system.in
}
It doesn't make sense, since receive() will keep waiting util receive something, it will never read from system.in concurrently.
So how can i achieve my requirement without using a thread?
Inspired by #Andriy Kryvtsun's answer, i did a quick test
As he said, this is somehow using non-blocking read, and keep letting socket timeout, to emulate
InputStream ins = System.in;
byte buffer[] = new byte[512];
BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
DatagramSocket clientSocket = new DatagramSocket();
System.out.println("From buffer:" + clientSocket.getLocalPort());
while (true) {
try {
if (ins.available() > 0) {
String line = reader.readLine();
System.out.println("Read:" + line);
} else {
DatagramPacket pack = new DatagramPacket(buffer,buffer.length);
clientSocket.setSoTimeout(2000);
clientSocket.receive(pack);
System.out.println("Receive: " + new String(pack.getData()));
}
} catch (IOException e1) {
}
}
Use unblocking method call InputStream#available() to get info if something ready for reading before using blocking Scanner#hasNext() call.
Also you can call DatagramSocket#setSoTimeout(int timeout) before call blocking receive(DatagramPacket p) method. Thus you can break infinity waiting inside receive method after timeout period emulating unblocking reading.
how can I download strings with two different objects BufferedReader and two different objects Scanner from a single socket with two different threads?
I already tried this solution below but myReader1, after reading from Socket, is with invalid characters how can I fix? You might suggest a workaround? Thanks a lot in advance
//Socket TCP declaration
InetAddress serverAddr = InetAddress.getByName(IP);
try
{
Socket mySocket = new Socket(serverAddr, PORT);
}
catch(Exception e)
{
e.printStackTrace();
}
//Thread 1
Thread t1 = new Thread(new Runnable()
{
#Override
public void run()
{
BufferedReader myReader1 = new BufferedReader(new InputStreamReader(mySocket.getInputStream(), "UTF-8"));
Scanner myScanner1 = new Scanner(myReader1).useDelimiter("\0");
synchronized(mySocket)
{
while(mySocket.isConnected() && myScanner1.hasNext())
{
String s = myScanner1.next();
}
}
}
});
Thread t2 = new Thread(new Runnable()
{
#Override
public void run()
{
BufferedReader myReader2 = new BufferedReader(new InputStreamReader(mySocket.getInputStream(), "UTF-8"));
Scanner myScanner2 = new Scanner(myReader2).useDelimiter("\0");
synchronized(mySocket)
{
while(mySocket.isConnected() && myScanner2.hasNext())
{
String s = myScanner2.next();
}
}
}
});
t1.start();
t2.start();
how can I download strings with two different objects BufferedReader and two different objects Scanner from a single socket with two different threads?
You can't .
You will never get this to work. Because of aspects of TCP you can't control, the data will arrive in unpredictable quanta, and the BufferedReaders will steal it from each other in unpredictable ways. Ditto the Scanners themselves if they have internal buffering.
In any case what you are trying to do has no actual meaning. What are you expecting the two threads to do that a single thread won't? If for example you're expecting them to read alternately, they won't. If you're expecting to be able to confidently send one string intended for thread 1 and another string intended for thread 2, you can't. It is impossible.
I already tried this solution below but myReader1, after reading from Socket, is with invalid characters how can I fix? You might suggest a workaround?
You won't succeed in getting anything working at all along the lines you've started on, but the basis of any solution must be a single Scanner and a single BufferedReader per socket. If you must have two threads you will need two sockets, with a BufferedReader and Scanner each.
try
{
Socket mySocket = new Socket(serverAddr, PORT);
}
catch(Exception e)
{
e.printStackTrace();
}
Don't write code like this. First, you should only be catching IOException. Second, all the code that depends on the success of this code should be logically inside this try block. It should be impossible for any code anywhere to access the mySocket variable unless this code has succeeded.
while(mySocket.isConnected() && myScanner1.hasNext())
The isConnected() test is pointless here. It will never return false. It doesn't magically become false when the peer disconnects.
I have a function that reads serial data from an embedded device. My program shows a picture and a title and basically the device acts as a buzzer for a game. Is there a way to check for serial data for lets say 5 seconds and if nothing was received to continue with the code (go to the next picture and title). My current function looks like this.
public String getUARTLine(){
String inputLine = null;
try{
BufferedReader input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
inputLine = input.readLine();
if (inputLine.length() == 0)
return null;
} catch (IOException e){
//System.out.println("IOException: " + e);
return null;
}
return inputLine;
}
You can start reading data from serialPort and start a timer in other thread. Something like this:
class ReadItWithTimeLimit implements Runnable {
int miliSeconds;
BufferedReader reader;
public ReadItWithTimeLimit (BufferedReader reader, int miliSeconds) {
this.miliSeconds = miliSeconds;
this.reader = reader;
}
public void run() {
Thread.sleep(miliSeconds);
this.reader.close();
}
}
So you can call it from your code:
// ...
BufferedReader input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
new Thread(new ReadItWithTimeLimit(input, 5000)).start();
inputLine = input.readLine();
// ...
This code is without excaption handling, so it requires some finalization work...
Drop the buffer. Start a read on the input stream yourself and in a different thread count 5 seconds. After that, close the stream (that will cause the read function to return -1).
Yes you can. You can use a separate timer thread that triggers the timeout that closes the input stream (that will cause input.readLine() to come back with an IOException). Or you can use java.nio. However I personally prefer the first method.