I'm creating an update client via Sockets and I'm getting a Broken Pipe on the server side. The server accepts a client socket and responds to the same socket with either a message or a large byte array (~180MB). The error does not happen when testing locally (both client and server on the same machine) and it seems that it happens while sending the byte array. I'm not specifying a time out on the client socket and don't know why it is closing before reading the full response. Its my first time working with sockets and any help would be appreciated.
My Client Socket Code:
public static Response makeRequest(Request req) throws IOException {
Response response = null;
Socket echoSocket = null;
ObjectOutputStream out = null;
ObjectInputStream in = null;
echoSocket = new Socket(serverHost, 10008);
out = new ObjectOutputStream(echoSocket.getOutputStream());
in = new ObjectInputStream(
echoSocket.getInputStream());
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
out.writeObject(req);
try {
response = (Response)in.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.close();
in.close();
stdIn.close();
echoSocket.close();
return response;
}
Response is just a POJO holding the response (string/byte[] and other data)
My Server Code (copied an example of Sun/Oracle site and added my code to it)
public class Server extends Thread {
private Socket clientSocket;
public Server(Socket clientSocket) {
this.clientSocket = clientSocket;
start();
}
public void run()
{
{
System.out.println ("New Communication Thread Started");
try {
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
Request request = null;
try {
request = (Request)in.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
UpdateDAO dao = new UpdateDAO();
ClientDAO cdao = new ClientDAO();
Update update = null;
Client client = null;
Session s = HibernateUtil.currentSession();
Transaction t = s.beginTransaction();
if (request != null) {
client = cdao.getClient(request.getClientId());
LogItem log = new LogItem();
log.setClient(client);
log.setTimestamp(new Date());
log.setAction(request.getAction());
if (request.getResponse() != null) {
update = dao.getUpdate(request.getResponse().getUpdateId());
}
TaskContext ctx = new TaskContext(request, client, update, log);
System.out.println("Action: " + request.getAction().getDescription());
Task task = TaskFactory.getTask(request.getAction());
System.out.println(task.getClass().getName());
Response response = task.perform(ctx);
out.writeObject(response);
log.setClientTaskDescription(request.getMessage());
log.setUpdate(ctx.getUpdate());
dao.save(ctx.getLog());
if (ctx.getUpdate() != null) {
dao.update(ctx.getUpdate());
}
} else {
out.writeObject(new Response("what"));
}
t.commit();
out.close();
in.close();
clientSocket.close();
}
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
}
}
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(10008);
System.out.println ("Connection Socket Created");
try {
while (true)
{
System.out.println ("Waiting for Connection");
new Server (serverSocket.accept());
}
}
catch (IOException e)
{
System.err.println("Accept failed.");
System.exit(1);
}
}
catch (IOException e)
{
System.err.println("Could not listen on port: 10008.");
System.exit(1);
}
finally
{
try {
serverSocket.close();
}
catch (IOException e)
{
System.err.println("Could not close port: 10008.");
System.exit(1);
}
}
}
}
If the client is, in fact, running out of memory:
java -Xmx512m -jar <the jar>
or
java -Xmx512m com.foo.blah.YourClass
would increase the maximum heap for the client/server. Keep in mind you may have to increase the heap for both sides of the pipe since both sides would be reading all ~180mb into memory at runtime.
Related
I want to have a Server that is running and receives messages from Clients such as another Java Applications. I am doing this via BufferedReader with an InputStream and as long as i do it a single time it works as expected. The message gets processed by the method and writes the Test Message of the received message on the screen, but if i let it run in a while loop it says -
java.net.SocketException: Connection reset
So once the Server got a message i dont know how to get a second one, or any following one.
My main source code is:
public static void main (String[] args) {
int port = 13337;
BufferedReader msgFromClient = null;
PrintWriter msgToClient = null;
timeDate td = new timeDate(); //Class i did for myself to get time/date
ServerSocket s_socket = null;
try {
s_socket = new ServerSocket(port);
System.out.println("Server startet at "+td.getCurrDate()+" "+td.getCurrTime());
}
catch (IOException ioe) {
System.out.println("Server on Port "+port+" couldnt be created. \nException: "+ioe.getMessage());
}
Socket socket = null;
try {
socket = s_socket.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
msgFromClient = utils.createInputStream(socket);
} catch (IOException ioe) {
System.out.println("Creation of an Input Stream failed.\n Exception - "+ioe);
}
try {
msgToClient = utils.createOutputStream(socket);
} catch (IOException ioe) {
System.out.println("Creation of an Output Stream failed.\n Exception - "+ioe);
}
String input = null;
while (true) {
try {
input = msgFromClient.readLine();
} catch (IOException ioe) {
System.out.println(ioe);
}
if(input!=null) {
System.out.println("Jumping out of loop: "+input);
utils.processCode(input);
}
}
The both classes to create the streams look like this:
public static BufferedReader createInputStream (Socket socket) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
return br;
}
public static PrintWriter createOutputStream (Socket socket) throws IOException {
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
return pw;
}
The "processCode" class then simply is a switch.
Socket socket = null;
try {
socket = s_socket.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
You only accept one Connection an after this you are doing your handling. You need to open an new Thread for every connection
ExecutorService threadLimit = Executors.newFixedThreadPool(10);
while(true) {
Socket s = serverSocket.accept();
treadLimit.submit(new HandleThread(s));
}
I have a client-server application. Right now, I'm trying to test sending messages from the client to the server and then read them from the server. I'm using ObjectInputStream and ObjectOutputStream to transfer message objects between the client and server.
However, when I try to write an object from the client, it results in a SocketException.
Server code:
while (true) {
try {
log.trace("Waiting for connection.");
Socket clientSocket = socket.accept();
log.trace("Socket connected");
/* create thread */
new Thread(new RequestRunner(clientSocket, serverID)).start();
} catch (SocketTimeoutException e) {
log.trace("Socket timed out.");
socket.close();
break;
} catch (IOException e) {
log.error("Cannot accept connection...");
break;
}
}
Server Thread:
public class RequestRunner implements Runnable {
....
public RequestRunner(Socket socket, UUID serverID) {
client = socket;
this.serverID = serverID;
}
/**
* Start the thread for the request
*/
public void run() {
log.trace("Thread started for socket");
try {
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
} catch (IOException e) {
log.error("Cannot intialize streams...");
return;
}
while(client.isConnected()) {
/* initialize streams */
try {
/* read message */
Object obj = in.readObject(); // does not block
MessageFrame msg = (MessageFrame) obj;
processRequest(msg);
} catch (IOException e) {
; // triggers everytime
//log.error("IO error occured while trying to get input/output stream from socket");
} catch (ClassNotFoundException e) {
log.error("Cannot read MessageFrame");
}
}
}
}
Client code:
public void init(int port) throws IOException {
log.trace("intializing to port " + port);
clientID = UUID.randomUUID();
socket = new Socket("0.0.0.0",port);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
}
public void sendEcho() throws Exception {
while(socket.isConnected()) {
try {
log.trace("Sending echo..");
msg = new EchoMessage(clientID);
curMsgID = msg.getMsgID();
out.writeObject(msg); // throws SocketException, socket closed
out.flush();
break;
} catch (SocketException e) {
log.error ("Cannot send echo.. socket closed.");
break;
} catch (IOException e) {
continue;
}
}
}
The statement out.writeObject(msg) causes a ServerSocket exception with Socket closed as the reason. And the server does not register receiving an object from in.readObject().
netstat shows the connection as established, the error occurs when I try to write the object.
What am I doing wrong ?
You should only have one InputStream and one OutputStream.
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
Should be:
out = client.getOutputStream();
in = client.getInputStream()
And you should change it in the client code when getting the streams from the sockets as well.
i've done a socket programming with client residing on android and server residing on the desktop ....... whenever server is down as we know client lost the connection.....so it undergoes a looping until it connects to server.......
here the problem is in the below code
tabletclient = new Socket(SERVER_IP, TAB_SERVER_PORT);
in the while loop in the case of lost connection.........but when the connection is on it again creates a new object........
can anyone please tell me how to solve this problem..........
In the client side
while(true){
try {
tabletclient = new Socket(SERVER_IP, TAB_SERVER_PORT);
tabletout = new PrintWriter(tabletclient.getOutputStream());
in = new Scanner(tabletclient.getInputStream());
try
{
if((line = in.nextLine())!=null)
{
// my task to be done
}
}catch(Exception d){
System.out.println("Connection from server has lost.........tabletclient.isConnected()----->"+tabletclient.isConnected());
}
} catch (UnknownHostException e) { System.out.println("Entered 2.........");
} catch (IOException e) { System.out.println("Entered 3.........");e.printStackTrace();
}
}
In in the Server side
:
:
private Set <Socket> TABhs=new HashSet<Socket>();
:
:
new Thread(new TABServerThread()).start(); // runs in background
:
:
:
class ServerThread implements Runnable {
private ServerSocket server;
#Override
public void run() {
try {
server = new ServerSocket(SERVER_PORT);
System.out.println("Server Start the server at port " + SERVER_PORT
+ " and waiting for clients...");
while (true) {
Socket socket = server.accept();
System.out.println("Server Accept socket connection: "
+ socket.getLocalAddress());
new Thread(new ClientHandler(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static PrintWriter out;
class ClientHandler implements Runnable {
private Socket clientSocket;
private Scanner in;
public ClientHandler(Socket clietSocket) {
this.clientSocket = clietSocket;
}
#Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream());
in = new Scanner(clientSocket.getInputStream());
String line;
System.out.println("ClientHandlerThread Start communication with : "+ clientSocket.getLocalAddress());
try{
while((line = in.nextLine()) != null) {
System.out.println("ClientHandlerThread Client says: " + line);
String dat[]=line.split("#");
String query="insert into table_orders (tableno,kotno, orders,status) values('"+dat[1]+"','"+dat[0]+"','"+dat[2]+"','pending')";
try {
int i= dbGetDet.insertDetails(query);
if(i>0)
{
fillTable();
filtercomboBox();
out.print("success");
out.flush();
for(Socket so:TABhs)
{
PrintWriter ot = new PrintWriter(so.getOutputStream());
ot.println("tableallocation#"+dat[1]);
ot.flush();
}
System.out.println("SENDED 'SUCCESS' TO CLIENT");
}
} catch (Exception ex) {
Logger.getLogger(MYClientclass.class.getName()).log(Level.SEVERE, null, ex);
}
// }
}
}catch(Exception r){}
} catch (IOException e) {
e.printStackTrace();
}
}
}
In the Button click of server
String stat=status_combo.getSelectedItem().toString();
String tables=tableno_combo.getSelectedItem().toString();
String kotno=kotno_combo.getSelectedItem().toString();
if(stat.equals("Processing"))
{
try {
TABhs = new CopyOnWriteArraySet(TABhs);
int soint=1;
System.out.println("TABhs Processing--------------------->"+TABhs.size());
for(Iterator <Socket> it=TABhs.iterator();it.hasNext();)
{
Socket so=it.next();
System.out.println("SEEE SOCKET Processing"+soint+"----->"+so.isClosed());
PrintWriter ot = new PrintWriter(so.getOutputStream());
ot.println("tableupdate#"+tables+"#"+kotno+"#processing");
ot.flush();
JOptionPane.showMessageDialog(rootPane, "<html><body>Table Kot Status Changed to <b>Processing</b></body></html>");
soint++;
}
System.out.println("TABhs Processing--------------------->"+TABhs.size());
}
catch (Exception ex) {
Logger.getLogger(MYClientclass.class.getName()).log(Level.SEVERE, null, ex);
}
}
NOW EACH TIME WHEN BUTTON IS CLICKED THE OUTPUT IS AS GIVEN BELOW
FISRT CLICK
SEEE SOCKET Ready 1----->false
Server Accept socket connection: /192.168.1.74
SEEE SOCKET Ready 2----->false
TABhs--------------------->2
SECOND CLICK
SEEE SOCKET Ready 1----->false
SEEE SOCKET Ready 2----->false
Server Accept socket connection: /192.168.1.74
SEEE SOCKET Ready 3----->false
TABhs--------------------->4
FOURTH CLICK
SEEE SOCKET Ready 1----->false
SEEE SOCKET Ready 2----->false
SEEE SOCKET Ready 3----->false
Server Accept socket connection: /192.168.1.74
SEEE SOCKET Ready 4----->false
TABhs--------------------->5
I think the problem is at the client's side you read a line and then create a new connection.
I think you must keep reading the socket until it's closed or an error occurs.
For example:
while (true)
{
tabletclient = null;
int loop = 0;
// loop until a connection is established
while (tabletclient == null)
{
try
{
tabletclient = new Socket(SERVER_IP, TAB_SERVER_PORT);
}
catch (Exception e)
{
e.printStackTrace();
// set the value to quit when no connection could be established
if (loop++ > 100)
return;
}
}
try
{
tabletout = new PrintWriter(tabletclient.getOutputStream());
in = new Scanner(tabletclient.getInputStream());
// read the socket until it's closed or an error occurs
try
{
while ((line = in.nextLine()) != null)
{
// my task to be done
}
}
catch (Exception d)
{
System.out.println("Connection from server has lost.........tabletclient.isConnected()----->"
+ tabletclient.isConnected());
}
tabletsocket.close();
}
catch (UnknownHostException e)
{
System.out.println("Entered 2.........");
}
catch (IOException e)
{
System.out.println("Entered 3.........");
e.printStackTrace();
}
}
Also, you must close the server side when the transfer from the server to the client is completed.
This may be a stupid question, but here goes.
Im writing this chat program, where there is a server, and clients that can connect to it. I want to implement private messaging into the program, but I don't know how to get the clients to directly connect to eachother. For the server, I used a ServerSocket, which runs on a single port. To get that to work, I needed to forward a port to the server. Is there a way to get the clients to wait for connections, without forwarding a port to them?
Thanks
The whole point of TCP/IP is that a single client connects to a predefined port on a server. So yes, you'll also need to have a ServerSocket on the client that's going to accept the direct connection. You'll almost always run into trouble with port forwarding and the like, which is why UPnP was invented one day.
What you are trying to do is 'peer to peer' connectivity, aka P2P, which is always, by its very definition, plagued by firewalling problems. As such it's usually, especially for a chat, easier to use the central server as 'switchboard' server and relay the private messages as well.
I've written not long time ago a template for multiple client - server application, that might help you to solve your problem. The rest of your question was already answerd by #Niels, I think ;)
import java.net.*;
import java.io.*;
class ServeConnection extends Thread {
private Socket socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
public ServeConnection(Socket s) throws IOException {
// init connection with client
socket = s;
try {
in = new BufferedReader(new InputStreamReader(
this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(), true);
} catch (IOException e) {
System.err.println("Couldn't get I/O.");
System.exit(1);
}
start();
}
public void run() {
System.out.println("client accepted from: " + socket.getInetAddress()
+ ":" + socket.getPort());
// get commands from client, until is he communicating or until no error
// occurs
String inputLine, outputLine;
try {
while ((inputLine = in.readLine()) != null) {
System.out.println("request: " + inputLine);
outputLine = inputLine;
out.println("I've recived "+outputLine);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("server ending");
out.close();
try {
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Server {
public static void svr_main(int port) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.err.println("Could not listen on port: " + port);
System.exit(1);
}
System.out.println("Server ready");
try {
while (true) {
Socket socket = serverSocket.accept();
try {
new ServeConnection(socket);
} catch (IOException e) {
System.err.println("IO Exception");
}
}
} finally {
serverSocket.close();
}
}
}
class Client {
static Socket echoSocket = null;
static PrintWriter out = null;
static BufferedReader in = null;
public static void cli_main(int port, String servername) throws
IOException {
try {
echoSocket = new Socket(servername, port);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + servername);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for " + servername);
System.exit(1);
}
System.out.println("Client ready!");
while (true) {
inputLine = (in.readLine().toString());
if (inputLine == null) {
System.out.println("Client closing!");
break;
}
// get the input and tokenize it
String[] tokens = inputLine.split(" ");
}
out.close();
in.close();
echoSocket.close();
System.out.println("Client closing");
}
}
public class MyClientServerSnippet{
public static void main(String[] args) throws IOException {
if (args.length == 0) {
System.err.println("Client: java snippet.MyClientServerSnippet<hostname> <port>");
System.err.println("Server: java snippet.MyClientServerSnippet<port>");
System.exit(1);
}
else if (args.length > 1) {
System.out.println("Starting client...\n");
Client client = new Client();
client.cli_main(3049, "127.0.0.1");
} else {
System.out.println("Starting server...\n");
Server server = new Server();
server.svr_main(3049);
}
}
}
I have a problem with my Java program. It has a socket connection between a server and many client. Here is the server (the part which concerns the problem):
private static ArrayList<ParallelServer> clientConnected = new ArrayList<ParallelServer>();
public Server(int port) {
this.port = port;
if (!startServer())
JOptionPane.showMessageDialog(new JFrame(""),
"Error!", "ERROR!",
JOptionPane.ERROR_MESSAGE);
}
private boolean startServer() {
try {
server = new ServerSocket(port);
loadDatabase();
} catch (IOException ex) {
ex.printStackTrace();
return false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return true;
}
public void runServer() {
while (true) {
try {
client = server.accept();
ParallelServer pServer = new ParallelServer(client);
clientConnected.add(pServer);
Thread thread = new Thread(pServer);
thread.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void sendBroadcast(String username) throws IOException {
for(int i = 0; i < clientConnected.size(); i++)
clientConnected.get(i).sendAnswer("#change," + username);
}
The parallel server is:
private Socket client;
private InputStreamReader inputstreamreader;
private BufferedReader bufferedreader;
private PrintWriter printwriter;
public ParallelServer(Socket client) {
this.client = client;
}
public void run() {
try {
inputstreamreader = new InputStreamReader(client.getInputStream());
bufferedreader = new BufferedReader(inputstreamreader);
printwriter = new PrintWriter(client.getOutputStream(), true);
String lineread = "";
while (client.isConnected()) {
lineread = bufferedreader.readLine();
doCommand(lineread);
}
} catch (UnknownHostException unhe) {
} catch (InterruptedIOException intioe) {
} catch (IOException ioe) {
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void sendAnswer(String answer) throws IOException {
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.println(answer);
printwriter.flush();
}
And here is the client:
private String serverurl = "localhost";
private int serverport = 7777;
private PrintWriter printwriter;
private InputStreamReader inputstreamreader;
private BufferedReader bufferedreader;
private Socket server;
public Client() {
server = null;
try {
server = new Socket(serverurl, serverport);
server.setSoTimeout(5000);
} catch (UnknownHostException unhe) {
System.out.println("UnknownHostException: " + unhe.getMessage());
} catch (InterruptedIOException intioe) {
System.out.println("Timeout while attempting to establish socket connection.");
} catch (IOException ioe) {
JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROE!",JOptionPane.ERROR_MESSAGE);
}
}
public String sendCommand(String command) throws IOException {
if(server == null) {
try {
server = new Socket(serverurl, serverport);
server.setSoTimeout(5000);
} catch (UnknownHostException unhe) {
System.out.println("UnknownHostException: " + unhe.getMessage());
} catch (InterruptedIOException intioe) {
System.out.println("Timeout while attempting to establish socket connection.");
} catch (IOException ioe) {
JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROR!",JOptionPane.ERROR_MESSAGE);
}
}
if(server != null) {
printwriter = new PrintWriter(server.getOutputStream(), true);
printwriter.println(command);
printwriter.flush();
inputstreamreader = new InputStreamReader(server.getInputStream());
bufferedreader = new BufferedReader(inputstreamreader);
return bufferedreader.readLine();
}
else
return "#serverProblem";
}
The program is a simple online game with turns. Players' turns are created with a queue and when a player passes his turn, the server send a broadcast message which say "Now it is 'Player 1' turn." (for instance). My problem is that when a client receive the message, its like it add the answer "Now it is 'Player 1' turn." to the next message it will receive. In my case: when a player passes his turn, he sends "#passTurn,username". The ParallelServer class polls it from the queue, puts it at the bottom of the queue, sends the client "#ok" to tell it that the turn has changed successfully and tells the Server class to send the broadcast message. Then, when the same client will try do do a further action, it will consider "Now it is 'Player 1' turn." as the answer the server has given to it. Instead, I would like that the server and the clients work as always and when the broadcast message is cought, the client is notified without any collateral effect.
What can I do?
Thanks.
Your bi-directional message passing mechanism should look something like this:
Server:
Wait on any client InputStream
if (broadcast)
broadcast_message()
else
process_message()
Client:
Receiving Thread:
Wait on server broadcast
Sending Thread:
Wait on messages to be sent to server from the User Input
This should do the trick :)
Hope it helps. Cheers!