I have a server and client application. They both use a BufferedWriter-InputStreamReader-InputStream to read information coming from the server, or coming from the client
I have it working so I can use
bw.write("command");
to execute a command on the server side, and output the information back to the client-side.
However, I am running into trouble doing it twice, for two different commands. Here's the code:
Server-sided code:
public void run() {
try {
while (true) {
socket.setTcpNoDelay(true);
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String input = br.readLine();
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
if (input.equals("increment")) {
bw.write(String.valueOf(totalBets.incrementAndGet()));
bw.newLine();
bw.flush();
} else if(input.equals("generate")) {
Random rand = new Random();
bw.write(String.valueOf(rand.nextDouble()*99));
bw.newLine();
bw.flush();
}
}
}
Client-sided code:
public void actionPerformed(ActionEvent arg0) {
try {
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
bw.write("increment" + "\n");
bw.flush();
String id = br.readLine();
bw.write("generate");
bw.flush();
String roll = br.readLine();
}
}
The first String id gets the output from running the bw.write("increment"), but when I try to run bw.write("generate"), it freezes when running the line: String roll = br.readLine();
Any help?
Thank you!
I suggest that you use PrintWriter rather than BufferedWriter. Use BufferedReader to read without leaving data in the underlying operating system's buffers, so they will be buffered at application level, but for writing you want it to go out as soon as you send one complete 'command'.
With a PrintWriter you can also use println which should solve your problem.
You're losing data, or risking it, by creating multiple BufferedReaders. Use the same one for the life of the socket. Ditto the BufferedWriter.
Related
I'm trying to learn socket programming in Java but unfortunately I'm running into some behaviour that I don't understand. I have a very simple client program that connect to a server socket and sends some text that gets echoed back. Said client program looks like this:
try(
Socket socket = new Socket("127.0.0.1", 5001);
OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
){
String userInput = "";
while (!userInput.toLowerCase().equals("quit")) {
userInput = stdIn.readLine();
writer.write(userInput);
writer.flush();
System.out.println("Server response: " + reader.readLine());
}
}
catch(Exception e) {e.printStackTrace();}
When I run this program the first line that I enter gets sent to the server but after that I can enter as many lines as I want and nothing gets sent. I also never see anything printed out by the System.out.println() line.
But if I switch out the OutputStreamWriter for a PrintWriter everything works as it should! Here's the code with PrintWriter:
try(
Socket socket = new Socket("127.0.0.1", 5001);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
){
String userInput = "";
while (!userInput.toLowerCase().equals("quit")) {
userInput = stdIn.readLine();
writer.println(userInput);
System.out.println("Server response: " + reader.readLine());
}
}
catch(Exception e) {e.printStackTrace();}
Anyone have any idea why the first of the above two programs acts weird while the second one works? If anyone can tell me what the difference between writing with an OutputStreamWriter vs a PrintWriter is then that might tell me what's going on.
Note that the difference between write() and println() is that println() adds a linebreak after the data while write() does not.
So if your server uses readLine() to receive the data with a client using write() it might wait forever for the end of the line to read without receiving it.
So writer.write(userInput + "\n") might do the trick.
What is happenning:
Main server -> String("isalive") => Other server
Other server -> String("alive") => Main server
Ports and stuff are configured (both servers are dedicated machines)
And code. The place where stuff seem to break is (i added debug messages....)
reader.readLine();
Main server code:
Socket clientSocket = new Socket(key, 6789);
if(clientSocket.isConnected() && !clientSocket.isClosed()){
String in;
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(isalive);
outToServer.flush();
//it wont go pass this one
in = inFromServer.readLine();
if(in.equals("alive")){
if(!Data.hosts.get(key)){
Data.hosts.put(key, true);
}
}
outToServer.close();
inFromServer.close();
clientSocket.close();
It wont go pass this one because it will stop at the other server.
Code:
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
//stuck here
rec = inFromClient.readLine();
if(rec.equals("isalive")){
outToClient.writeBytes("alive");
}
inFromClient.close();
outToClient.flush();
outToClient.close();
connectionSocket.close();
Thanks in advance.
You should not combine DataOutputStream and BufferedReader.
Consider using PrintWriter instead and specify character encodings as well (to be safe).
PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
writer.println("Hello.");
writer.flush();
reader.readLine();
I have implemented a client/server to send files . When there is no more messages exchanged after sending the file , the code works perfectly , but if the client sends some string to the server directly after the code of receiving the file both client and server stop doing anything and the file is not sent it's something like if they both get stuck in deadlock but I'm not really sure :
Here is the code to send the file without sending anything after it , which works:
Client
String filename;
BufferedReader UIn = new BufferedReader(new InputStreamReader(System.in));
Socket peer = new Socket("localhost",9999);
System.out.print("Enter the file name to download :");
filename= UIn.readLine();
///////////////////////////////
DataOutputStream OutToServer;
OutToServer = new DataOutputStream(peer.getOutputStream());
OutToServer.writeBytes(filename+"\n");
FileOutputStream fos = new FileOutputStream(new File("D:/new.txt"));
BufferedOutputStream out = new BufferedOutputStream(fos);
InputStream in = peer.getInputStream();
buffer = new byte[1024];
while((count=in.read(buffer))>0)
{
fos.write(buffer, 0, count);
System.out.println(buffer);
}
fos.close();
System.out.println("done");
Server:
ServerSocket server =null;
try {
server = new ServerSocket(9999);
while(true)
{
client= server.accept();
//System.out.println("Connection accepted");
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
DataOutputStream outToclient =new DataOutputStream(client.getOutputStream());
String request=inFromClient.readLine();
file = new File(request);
if (file.exists())
{
OutputStream out = client.getOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
while((count =in.read(buffer)) >0)
{
out.write(buffer,0,count);
out.flush();
}
}
// System.out.println(request);
// outToclient.writeBytes("alaa\n");
}
} catch (IOException ex) {
Logger.getLogger(ServerWork.class.getName()).log(Level.SEVERE, null, ex);
}
But if I try to send anything after the loop between client and server it stops working . Is it because I'm using readLine() and writeBytes()?
You are using both DataOutputStream and OutputStream. I think that they
should work together but what I guess you should do is to flush the buffer (or close it).
After you're done writing everything you want to send, some data may still be in the buffer. Now you will have to flush the buffer, to force it to send all the data.(as it is said here).
outToclient.writeBytes("alaa\n");
outToclient.flush();
I want to programm al small "chat" Programm using TLS
I am having trouble with SSL Sockets an Input streams. The TLS part works fine.
My Problem is : "bufferedreader.ready()" always returns false.
if i delete teh if -satetmant if works "fine". The programm waits until there is an \n or \r and prints is to System.out. But I can not send messages in that time.
"client"
InputStream inputstream = System.in;
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
InputStream inputstream1 = socket.getInputStream();
InputStreamReader inputstreamreader1 = new InputStreamReader(inputstream1);
BufferedReader bufferedreader1 = new BufferedReader(inputstreamreader1);
OutputStream outputstream = socket.getOutputStream();
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream);
BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
OutputStream outputstream1 = System.out;
OutputStreamWriter outputstreamwriter1 = new OutputStreamWriter(outputstream1);
BufferedWriter bufferedwriter1 = new BufferedWriter(outputstreamwriter1);
//Mitteilen, welchen Kommprofil zum verbindugn genutzt werden soll.
bufferedwriter.write("bez\n");
while (true) {
if (bufferedreader.ready()) {
bufferedwriter.write(bufferedreader.readLine() + '\n');
bufferedwriter.flush();
}
if (bufferedreader1.ready()) {
bufferedwriter1.write(bufferedreader1.readLine() + '\n');
bufferedwriter1.flush();
}
}
"Server":
InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
InputStream inputstream1 = System.in;
InputStreamReader inputstreamreader1 = new InputStreamReader(inputstream1);
BufferedReader bufferedreader1 = new BufferedReader(inputstreamreader1);
OutputStream outputstream = System.out;
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream);
BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
OutputStream outputstream1 = sslsocket.getOutputStream();
OutputStreamWriter outputstreamwriter1 = new OutputStreamWriter(outputstream1);
BufferedWriter bufferedwriter1 = new BufferedWriter(outputstreamwriter1);
while (true ) {
if (bufferedreader.ready()) {
bufferedwriter.write(bufferedreader.readLine() + '\n');
bufferedwriter.flush();
}
if (bufferedreader1.ready()) {
bufferedwriter1.write(bufferedreader1.readLine() + '\n');
bufferedwriter1.flush();
}
}
As you have nothing else to do in your loop except call readLine(), just call it. It will block until something arrives. You don't need to call ready() at all in thus situation, or indeed in its any situation.
I "solved" my Problem with this workaround:
public class CopyStreamThread extends Thread {
private BufferedWriter out;
private BufferedReader in;
public CopyStreamThread(BufferedWriter out, BufferedReader in) {
this.out = out;
this.in = in;
}
#Override
public void run() {
while (true) {
try {
out.write(in.readLine() + '\n');
out.flush();
} catch (IOException ex) {
Logger.getLogger(CopyStreamThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
"clinet/Server"
new CopyStreamThread(bufferedwriter, bufferedreader).start();
new CopyStreamThread(bufferedwriter1, bufferedreader1).start();
i divided the waitung for input in 2 threads which isnt a nice soulution but it works.
Thanks for support.
What I am trying to do is to read in data from a socket connection then write all of that to a file. My reader and all the related statements are below. Any ideas why it is not working? If you can see a more efficient way to do this that would also be useful.
(My full code does successfully connect to the socket)
EDIT: Added more of my code.
public static void main(String args[]) throws IOException
{
Date d = new Date();
int port = 5195;
String filename = "";
//set up the port the server will listen on
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(port));
while(true)
{
System.out.println("Waiting for connection");
SocketChannel sc = ssc.accept();
try
{
Socket skt = new Socket("localhost", port);
BufferedReader in = new BufferedReader(new InputStreamReader(skt.getInputStream()));
FileWriter logfile = new FileWriter(filename);
BufferedWriter out = new BufferedWriter(logfile);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
while ((inputLine = stdIn.readLine()) != null)
{
System.out.println("reading in data");
System.out.println(inputLine);
out.write(inputLine);
System.out.println("echo: " + in.readLine());
}
sc.close();
System.out.println("Connection closed");
}
You program requires you to type in a line for every line you read from the socket. Are you typing enough lines?
The lines you read from the console are written to the file, did you expect the lines from the socket to be written to the file?
Where are you closing the file (and the socket)
Another approach is to use a utility like Apache IOUtils
Socket skt = new Socket("localhost", port);
IOUtils.copy(skt.getInputStream(), new FileOutputStream(filename));
skt.close();
I think there's a typo in this line:
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
Change "System.in" to just "in":
BufferedReader stdIn = new BufferedReader(new InputStreamReader(in));
FYI, here is how I like to read sockets. I prefer to avoid the string encoding offered by the readers, and just go straight for raw bytes:
byte[] buf = new byte[4096];
InputStream in = skt.getInputStream()
FileOutputStream out = new FileOutputStream(filename);
int c;
while ((c = in.read(buf)) >= 0) {
if (c > 0) { out.write(buf, 0, c); }
}
out.flush();
out.close();
in.close();
Oh, cute, turns out that code is essentially what IOUtils.copy() does (+1 to Peter Lawrey!):
http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/CopyUtils.java?view=markup#l193