I am learning about sockets in java, but when I was running a program that sends messages from the client side to server side it doesn't show a message. If I enter some text on the client side it doesn't show up on the server side, but if I type endProcess it stops running. Which means that the message is going through it's just not showing up.
My Client.java code is here:
import java.net.*;
import java.io.*;
public class Client{
Socket soc;
DataInputStream dis;
DataOutputStream dos;
public Client(){
try{
soc = new Socket("(Address)",5000);
System.out.println("Connection Established");
dis = new DataInputStream(System.in);
dos = new DataOutputStream(soc.getOutputStream());
System.out.println("Streams connected");
}catch(UnknownHostException u){
System.out.println(u);
}catch(IOException i){
System.out.println(i);
}
String line = "";
while(!line.equals("endConnection")){
try{
line = dis.readUTF();
dos.writeUTF(line);
}catch(IOException i){
System.out.println(i);
}
}
try {
soc.close();
dis.close();
dos.close();
} catch (Exception e) {
System.out.println(e)
}
}
public static void main(String[] args) {
new Client();
}
}
Here is my Server.java code:
import java.net.*;
import java.io.*;
public class Server {
ServerSocket serSoc;
Socket soc;
DataInputStream dis;
public Server(){
try {
serSoc = new ServerSocket(5000);
System.out.println("Server Online");
soc = serSoc.accept();
System.out.println("Client Connected");
dis = new DataInputStream(new BufferedInputStream(soc.getInputStream()));
String line = "";
System.out.println("Waiting for input...");
while(!line.equals("endConnection")){
line = dis.readUTF();
System.out.println(line);
}
System.out.println("Client disconnected");
soc.close();
dis.close();
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
new Server();
}
}
There are many problems here.
Duplex protocol issues
line = dis.readUTF();
dos.writeUTF(line);
This isn't going to work; The dis.readUTF() line is going to block (freeze) until a line is read. The problem is, sometimes you have nothing to send in which case you want to read, and something you have nothing to read in which case you want to send. In practice you need to redesign this entirely; you need 2 threads. At which point you get into the issues of multicore, needing synchronization primitives and/or java.util.concurrent classes for all data that is shared between the 2 threads.
Alternatively, adopt a model that is strictly push or pull (where at any given time both parties already know who can send, and if the other party wants to send they simply cannot. For example, every party sends a simply 'NOTHING TO DO' message every second, trading places every time. This is quite an inefficient algorithm, of course. But could be written without involving multiple threads.
Flush and close issues
dos.writeUTF(line);
This doesn't actually send anything, or at least, isn't guaranteed to. To send any data on the internet, it gets wrapped in a packet which has lots of overhead. So, things are buffered until there's a full packet to send. Which means that line doesn't do anything. It just fills a buffer, no packets go out. You first need to close or flush. dos.flush() would help maybe. This is a big problem, because later you do:
soc.close();
dis.close();
dos.close();
You first close the socket, which, well, closes the socket. You then close the streams, which will also send anything that's still stuck in a buffer, except, that will fail, because the socket is already closed. In other words, the line you .writeUTF()-ed? It never gets there. You first shove it in a buffer, then you close the socket, then you send the buffer which won't work as the socket is already closed.
Broken error handling
} catch (Exception e) {
System.out.println(e);
}
Horrible. Don't do this. Your code reacts to any problem by printing something and just keeping right on going. That means if anything goes wrong, the client will start spamming an endless cavalcade of exception traces and locking up the system with any luck. You want the code to stop running when problems occur. Easiest way, by far, is to just stick throws IOException on your constructor and main method, which is allowed. Distant second best option is to configure your 'eh whatever' catch blocks as throw new RuntimeException("unhandled", e); instead of e.printStackTrace().
What you do (System.out.println(e);) is even worse - you are tossing away extremely useful information such as the stack trace and causal chain.
Related
I have a simple echo server, and I want when a connected user types anything to the server, all other clients and that client will get a the message + " | MOD".
It wont send to all clients now but it should and I just don't know what's wrong in my code, so now it will just send the message + " | MOD" to the client who sent the message but not to all others also as it should.
I just don't get it, I have a loop that goes through all clients, but it still won't send to all.
SERVER:
package com.murplyx.server;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
public static ServerSocket server;
public static ArrayList<Socket> clients = new ArrayList<Socket>();
public static void broadcast(String message) {
try {
for (Socket socket : clients) {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(message);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
server = new ServerSocket(9000);
while (true) {
clients.add(server.accept());
for (Socket socket : clients) {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
if (line != null) {
broadcast(line + " | MOD");
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
CLIENT:
package com.murplyx.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String args[]) {
try {
while (true) {
Socket socket = new Socket("localhost", 9000);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
out.println(input.readLine());
System.out.println(in.readLine());
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Please help.
Thanks alot.
One of the issues you have is that each client will repeatedly do read stdin, write socket, read socket, write stdout, ... ad infinitum.
When you broadcast all other clients are still typically sat in the read stdin phase, so they don't know that there's stuff waiting to be read on the socket. They're still waiting for the user to enter something.
One of the simplest options is to start two threads in each client - one just handles read stdin, write socket, ... and the other handles read socket, write stdout.
[Another (potentially more sophisticated) option us to use Java NIO to poll both the socket and stdin for available input at the same time].
A second issue is that you're blocking in the accept call in the server, and then reading from each socket in turn. You might accept in one thread, and have another thread per client read from just the client, and rebroadcast to the others. NIO can also be a good option here - you can poll for reads any any client.
I'm not exactly sure how ArrayLists play with sockets, so I definitely would go back to using a normal array for it (see the edited code here Java EchoTCPServer - Send to all clients)
Some things I see that I think can to be fixed:
On the Client:
-Stop closing the socket in the While loop. Close it OUTSIDE the while loop (When the client is done with the server). Also, declare the socket outside the Loop.
NOTE ON THIS: When a client makes a socket to connect to the server, it is automatically given a device port, so two different devices will never have the same IP connected to the server. A TCP connection consists of 2 ports, server socket and client socket, and the sockets are denoted by [deviceip:port,serverip:port] (iirc).
-Also, on the client you don't need to declare a new reader everytime you move through the while loop. Put that all outside. The only thing inside the while loop should be your readline + print statements.
-readLine is a blocking method. (just in case you don't know what that means, it means that readLine will make your program be stuck there until the it actually reads a line. To bypass this, you can use an if statement combined with the .ready() function. The ready function checks to see if there is anything to be "read in", so if there's no input it wont be stuck on "readLine".
On the Server:
-Like i said earlier, I'd change back to using a normal Array.
-Your server will still get stuck on .accept(). As such, you will never be able to read input from the clients except once after each connection. You can use a thread to listen instead, and it will still work.
eg: (this code goes with the code that's in the link i attached (also your question), put it before the while loop of your server)
// create a tcp listener thread to deal with listening to clients
Thread listenerThread = new Thread() {
public void run() {
String clientSentence;
while (true) {
//loop through each connected socket
for (int i = 0; i <= intLastSocket; i++) {
Socket z = clientSocket[i];
//make sure the socket is not null or closed (can't do anything
//with closed or null sockets
if ((z != null) && (!z.isClosed())) {
try {
// Deal with TCP input here
BufferedReader input = new BufferedReader(new
InputStreamReader(z.getInputStream()));
// read in a line but only if there is one
if (input.ready()) {
clientSentence = input.readLine();
}
} catch (IOException x) {
printTCP("IOException caught when reading in: "
+ x.toString());
}
if (clientSentence != null) {
System.out.println("Received from client: "
+ clientSentence);
//send this message to the client
outputStream[i].println(clientSentence + " | MOD");
}
// clear the input
clientSentence = null;
}
}
}
}
};
listenerThread.start();
I tried to make a console chat server. the main problem i am facing is that i can not send the message to the server.. as you can see in the img i uploaded that the server and the client are connected. but when i type anything in the client side. The client becomes unresponsive and i have to close the cmd prompt.
How can i fix this?
Is something wrong with my computer or is the code wrong?
public class MyClient
{
Socket s ;
DataInputStream din ;
DataOutputStream dout;
public MyClient()
{
try
{
s= new Socket("localhost",10);
System.out.println(s);
din = new DataInputStream(s.getInputStream());
dout= new DataOutputStream(s.getOutputStream());
ClientChat();
}
catch(Exception e)
{
System.err.println(e);
}
}
public void ClientChat() throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//Scanner s2 = new Scanner(System.in);
String s1;
System.out.println("start the conversation");
do
{
s1=br.readLine();
//s1=s2.nextLine();
dout.flush();
System.out.println("server:"+din.readUTF());
}
while(!s1.equals("stop"));
}
public static void main (String args[])
{
new MyClient();
}
}
The code snippet never calls dout.write*(), so nothing is ever sent over the Socket.
readLine() will block until a line of text is read, so messages sent to the client won't be printed until after the client types a 2nd line of text. You can fix this either by using asynchronous I/O or by moving the read loop into it's own Thread.
You need to make the server and client a thread, so they can work independently.
server as thread will wait for a client connections and will receive messages.
client as thread will work on its own.
problem is that they cannot run concurrently.
Use dout.writeUTF(s1); inside the do loop.
The writeUTF will allow you to write the subsequent message till then It will be stuck at readutf function.
The java.io.DataOuputStream.writeUTF(String str) method writes a string to the underlying output stream using modified UTF-8 encoding. Refer to this
I'm currently using a Java implementation of the Reliable UDP protocol, found [here][1]. The project has absolutely no tutorials so I have found it really hard to identify problems.
I have set up a client and server. The server runs on localhost:1234 and the client runs on localhost:1235. The server is first established, and loops listening for connections.
I then have set it to send a packet to the server. When a packet is sent, the server calls handlePacket() -
DataInputStream i = new DataInputStream(client.getSocket().getInputStream());
short packetID = i.readShort();
i = null;
switch(packetID){
case 3:
Packeta packeta = new Packeta(client);
break;
}
} catch (IOException e) {
e.printStackTrace();
}
I'm currently using a debugging with a small dummy class called Packeta. When the constructor is called, it reads from a stream and the logs to the console. However, always when constructing, it hangs for 10 seconds, before producing the error -
java.net.SocketException: Socket is closed ....
at
lessur.engine.net.packets.Packeta.(Packeta.java:15)
The constructor for Packeta -
public Packeta(LessurConnectedNode c) {
super((short)3, c);
try {
/*LINE 15*/ Logger.getLogger("adsfas").info("X was "+c.getSocket().getInputStream().read());
} catch (IOException e) {
e.printStackTrace();
}
}
It has something todo with the input streams. I don't know what is wrong, but from reading other threads, it might be todo with having multiple inputstreams. I'm lost on this, please help.
The problem was, I was passing the server to the socket listener, before the socket was fully initialized. FIXED!
package montecarlo;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
*
* #author hafiz
*/
public class PICalcDistributedMaster {
ObjectOutputStream ostream;
ObjectInputStream istream;
Socket s;
String numThrows;
public void go(){
Scanner input = new Scanner(System.in);
System.out.println("Please enter number of throws: ");
numThrows = input.next();
int num = Integer.parseInt(numThrows);
try{
ServerSocket sock = new ServerSocket(100);
s = new Socket("127.0.0.1",100);
System.out.println("Waiting for connection");
System.out.println("Connection received from " + s.getInetAddress());
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
pw.println("Sending Number");
pw.println(num);
ostream = new ObjectOutputStream(s.getOutputStream());
ostream.flush();
istream = new ObjectInputStream(s.getInputStream());
System.out.println("IO streams found");
istream.read(); //reads the input stream
}
catch (IOException ie){
ie.printStackTrace();
}
}
public static void main(String [] args){
PICalcDistributedMaster pim = new PICalcDistributedMaster();
pim.go();
}
}
i have adjusted the code to what you told me.I am still getting an error after running it more than once and i think it has to do with the garbage collector problem.My error is
java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:365)
at java.net.ServerSocket.bind(ServerSocket.java:319)
at java.net.ServerSocket.<init>(ServerSocket.java:185)
at java.net.ServerSocket.<init>(ServerSocket.java:97)
at montecarlo.PICalcDistributedMaster.go(PICalcDistributedMaster.java:31)
at montecarlo.PICalcDistributedMaster.main(PICalcDistributedMaster.java:56)
I assume the problem is with the socket it is binding to.I have tried different kinds but i cant still proceed
I'd like to suggest programming in smaller chunks. You've got a lot of code here and I don't think most of it ever runs:
ServerSocket sock = new ServerSocket(5000);
s = new Socket("127.0.0.1",5000);
s = sock.accept();
This code creates a server socket, binds it to a port.
Then you create a new socket s to connect to the server socket. (Which isn't yet listening.)
You destroy your new socket s with the sock.accept() result -- when you lose the last reference, the socket is free for garbage collection, and you only ever had one reference to it -- s.
The sock.accept() call probably ought to block until a new connection arrives. If it doesn't block, that means you triggered an exception even before all this code.
Incidentally, there's another instance of overwriting content nearly immediately after creating it:
String message = "connection successful";
message = (String) istream.readObject();
You'll never see connection successful from your program because you've overwritten the only reference you have to the string.
Probably the most egregious error in the entire program -- the one that is keeping you from making any real forward progress -- is that you throw away all the exception information:
try{
go(null);
}
catch(Exception e){
System.err.print("Connection terminated");
}
The catch(Exception e) { /* print message */ } means that you don't get any diagnostic information about what errors actually happened in your program. (Since you never use the parameter of go(), you should remove it completely and the needless null here, as well.)
One of these catch-all catch statements might be useful once you're confident that your product catches everything more specific, is nearly bullet-proof, and your customers demand an always-on reliable product. But it has no place in development -- you need to be alerted to faults in your programs with as much detail as possible so you can find and fix all your bugs.
Remove this. Get rid of your process() method completely -- it is only harmful.
I am feeling really stupid right now guys.... basically I am connecting over TCP on a local machine... and when I try to make the In/out streams at the client it wont get passed creating the object input stream. What gives? This stops after printing 2... no exceptions or anything... This isn't the first time I've used this class which is partialy why I am puzzled.
try {
System.out.println("1");
mySocket = new Socket("localhost", 11311);
System.out.println("12");
oos = new ObjectOutputStream(mySocket.getOutputStream());
System.out.println("2");
ois = new ObjectInputStream(mySocket.getInputStream());
System.out.println("13");
} catch (Exception e) {
e.printStackTrace();
}
From the specification of ObjectInputStream:
This constructor will block until the corresponding ObjectOutputStream
has written and flushed the header.
(For future readers:) I had the same problem because i made a silly change in server program and didn't test it for a long time then i was confused about why program is locked.
ServerSocket accepts the connection (responderSocket = serverSock.accept();) then suddenly for a inapropriate if (The silly change i mentioned!) program jumps out of the thread and because i didn't add a finally block to close streams and sockets the socket was left abandoned w/o sending or recieving anything (even stream headers). So in client side program there was no stream header (When i debbugged The code i saw that the last function executed before lock was:
public ObjectInputStream(InputStream in) throws IOException {
verifySubclass();
bin = new BlockDataInputStream(in);
handles = new HandleTable(10);
vlist = new ValidationList();
enableOverride = false;
readStreamHeader(); //// <== This function
bin.setBlockDataMode(true);
}
readStreamHeader();)
So be careful about what happens in server side, maybe problem isn't where you expecting it!