following is my client side code , that retrieves text from server and prints.
Socket socket = new Socket(ip, port);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
String string = "Hello!\n";
byte buffer[] = string.getBytes();
out.write(buffer);
while ((character = in.read()) != -1){
System.out.print((char) character);
}
I am getting the the correct values from the server , but it is happening again and again , how can i find out the length of the value sent.
-1 denotes the end of the stream, and is received when the connection is closed. If you want to keep the connection open and send multiple messages, you need some sort of protocol (kind of like agreement between both ends) that tells where the message ends. The are many ways to do this, but in your example you're writing a line terminator (\n) to the end of the message, so you could check for that at the other end. Another way is to write the amount of bytes you're about to send before the actual message contents.
Related
This is a a Java method that tries to crawl a designated web page. I am using writeUTF and readUTF for socket communications to a server.
static void get_html(String host, String page, int port) throws IOException {
Socket sock = new Socket(host, port);
String msg = MessageFormat.format("GET {0} HTTP/1.1\r\nHost: {1}\r\n\r\n", page, host);
DataOutputStream outToServer = new DataOutputStream(sock.getOutputStream());
DataInputStream inFromServer = new DataInputStream(sock.getInputStream());
InputStream stream = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8));
BufferedReader buf = new BufferedReader(new InputStreamReader(stream));
String outMsg;
while ((outMsg = buf.readLine()) != null) {
System.out.println("Sending message: " + outMsg);
outToServer.writeUTF(outMsg);
String inMsg;
try {
inMsg = inFromServer.readUTF();
} catch (EOFException eof) {
break;
}
System.out.println(inMsg);
}
sock.close();
}
The reason I am writing it this way was to mimic the c code, where you have a while loop of send() making all deliveries from a buffer, and another while loop of recv() from a buffer untill it hits 'null'. When execute my code, it just hangs there, I suspect that is due to a call of readUTF before I finished sending all my messages. If this is the case, is there any way to fix it?
You can't do this. HTTP is defined as text lines. writeUTF() does not write text, it writes a special format starting with a 16-bit binary length word. Similarly the HTTP server won't reply with that format into your readUTF() call. See the Javadoc.
You have to use binary streams and the write() method, with \r\n as the line terminator. Depending on the output format you may or may not be able to use readLine(). Best not, then you don't have to write two pieces of code: use binary streams again.
In fact you should throw it all away and use HttpURLConnection. Implementing HTTP is not as simple as may hastily be supposed.
I have a problem with socket programming in Java.
There is a server which has been written in python like this which I shouldn't not change.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send('from server\nnewline\0')
data = s.recv(BUFFER_SIZE)
s.close()
Now I want to write a code in Java which read the string from a server. Something like this:
public static String readStr(Socket client) throws IOException {
InputStreamReader inStream = new InputStreamReader(
client.getInputStream());
BufferedReader inBuff = new BufferedReader(inStream);
String answer = new String();
String str = inBuff.readLine();
while (str!=null) {
answer = answer.concat(str + "\n");
str = inBuff.readLine();
}
answer = answer.substring(0, answer.length() - 1);
System.out.println("answer:\n "+answer);
return answer;
}
But it seems that it blocks at line str = inBuff.readLine(); at the last line of the message. I tried the read() method but it was blocked too.
When designing a protocol over tcp, the best way is to include some kind of framer. This is done in the current protocol by the usage of a NUL byte.
When reading the data from the socket, you should first divide it into blocks/frames by some operations, before parsing the individual blocks.
A crude way to divide the packets into blocks is reading until you find a NUL byte, then returning that block as a byte array. (This is not the most efficient implementation)
public byte[] readPacket(InputStream in) throws IOException {
ByteArrayOutputStream tempStr = new ByteArrayOutputStream();
int read;
read=in.read();
while(read > 0){
tempStr.write(read);
read=in.read();
}
if(read == -1)
throw new EOFException();
return tempStr.toByteArray();
}
Because you now have proper frames for your data, you can now easily read the data:
byte[] frame = readPacket(in);
String[] lines = new String(frame, StandardCharsets.UTF8).split("\n");
// Do something with the lines
This is probably because the last line sent by the server does not end and readLine() method only returns when it reaches end of the line. Since you change the server's code. I recommend you use another method for reading from the stream. You may also use InputStreamReader class.
Apart from already mentioned inconsistent message/line ending - once with \n, second with \0, at the server there is no detection of end of the message. So the server will loop as long as the socket is not closed (or shut down for writing) at the client side. And as you have this line before closing the socket:
data = s.recv(BUFFER_SIZE)
in other words the client is waiting for some response from the server. But the server is stuck forever reading the message from the client in a loop.
So you need to either close the socket prior to that recv call or send some message (like empty line) and detect in on the server and eventually exit the loop.
I have a problem with writing an reading an array of bytes from client to server. The client actually writes all the bytes but the server does not seem to be able to read it. Here is the code for the client and server sides
Socket sock = new Socket(Interface.SERVER_IP, 4444);
PrintStream os = new PrintStream(sock.getOutputStream());
os.println("3");
DataOutputStream dOut = new DataOutputStream(sock.getOutputStream());
dOut.writeInt(data.length); // byte array created above
dOut.write(data);
and the server side is:
DataInputStream clientData = new DataInputStream(clientSocket.getInputStream());
int length = clientData.readInt();
System.out.println(length);
byte[] data = new byte[length]; // read length of incoming message
if(length>0) {
clientData.readFully(data, 0, data.length); // read the message
}
The server seems to be blocked at the line to read the length of the byte array. Please I really need help solving this
After you write the data, flush the output:
dOut.writeInt(data.length); // byte array created above
dOut.write(data);
dOut.flush();
Alternatively, close the stream (if you aren't going to use it again)...
dOut.writeInt(data.length); // byte array created above
dOut.write(data);
dOut.close();
Also note that your PrintWriter is printing a string value (of "3"). You are printing extra data to the stream that doesn't seem to get consumed on the server.
You're printing "3" to the socket but you're never reading it. So when you do readInt(), you're reading the "3" and a line terminator instead.
Don't mix multiple streams/writers on the same socket. Use the same ones for the life of the socket.
This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 7 years ago.
Presently My Server program can able to receive the file from client socket and able to save that received file in server machine.
But I am need to receive many files from client socket to server socket without closing and opening the socket connection every time.
I have written the code, this is working fine. But in this I am closing and opening the server and client socket connection in every iteration. But I need to do this without connecting and disconnecting both the sockets every time.
Please guide me seniors...
My Server code:
int img_count=1;
int bytesRead;
int current = 0;
byte [] mybytearray = new byte [100000];
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock=null;
// create socket
ServerSocket servsock = new ServerSocket(6668);
System.out.println("Waiting... for client req");
int i=0;
for ( i=0; i<9; i++)
{
sock = servsock.accept(); // Waiting for Client
String fname = "Image000"+(img_count++)+".JPG";
String fpath = "C:/RX_images/"+fname; // Image saving path
File myFile = new File (fpath);
is = sock.getInputStream();
fos = new FileOutputStream(myFile);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
fos.flush();
fos.close();
bos.close();
is.close();
sock.close();
} // End of for loop
servsock.close();
System.out.println("Received : "+ (i++)+ " Images");
My Client Code:
int i=0;
int img_count=1;
FileInputStream fis=null;
BufferedInputStream bis=null;
OutputStream os=null;
Socket client=null;
System.out.println("Sending...");
for ( i=0; i<9; i++)
{
client = new Socket("192.168.1.54",6668);
String fname = "Image000"+(img_count++)+".JPG";
String fpath = "C:/Tx_Images/"+fname; // Image path
File myFile = new File (fpath);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = client.getOutputStream();
os.write(mybytearray,0,mybytearray.length);
bis.close();
fis.close();
os.flush();
os.close();
client.close();
Thread.sleep(2000);
} // End of for loop
System.out.println("\n Sent : "+(i++)+" Images");
I am very new to java,
Help me please....
Since the socket is just a stream of bytes, in order to handle more than one file you are going to have to construct a simple protocol of some sort. In other words, the sender will have to send bytes that differentiate between the bytes in one file and the bytes in another. Since you are sending binary data, there is no series of bytes you can send to "mark" the beginning and/or/ending -- for example if you send 4 zero bytes at the end, that might be data and so the receiver cannot be sure if it's a marker or data. Two ways to handle it come to mind offhand -- break your file up into sections that are a maximum of N bytes, and send the sections one at a time. You will have to have a count of the bytes in each section, since at least one section will not have the same number of bytes as all other sections. Alternately,y you could count the bytes in the file and start with bytes that give that count, so the receiver knows how many bytes to expect. While you are giving the count, you could also give information such as the name and the type of file, if you wanted. Good luck.
This question really depends on whether you need the client to keep the connection open, or not. Typically you just need to keep the server side listening, and it's ok for the client to reconnect each time it needs to send a file.
Use an ExecutorService to keep the server side going and handle multiple connections with separate threads. Then just have the client connect and send what it needs to send and disconnect. See this question for a quick example: Multithreading Socket communication Client/Server
Also, look at how they close resources (finally) and stop the server in that example too. That is not related to your question, but you'll want to make your I/O and error handling more robust as well.
If you really do require that the server and client stay connected and send multiple files (or whatever data) then you'll need to implement some sort of a protocol as rcook notes, and you'll need to go deeper into networking and have a heartbeat and such. And, even if you do that, the client still needs to be smart enough to try to reconnect if the socket is closed, etc.
Just make simple protocol like:
File Name\r\n
File Size\r\n
File Data\r\n
File Name\r\n
File Size\r\n
File Data\r\n
....
I hope you will understand this. You can send file information initially then server will parse this file information, and make your server to read number bytes as you specified in file information. These will enable you to see file end marker and when to begin new file. BUT you must know file size before.
This will not work for data streams which have unknown length.
Make your server to read number of bytes you will be specifying, so server can know when to end file writing and begin new file or whether file is fully received before socket closes...
I am writing a byte array from a socket client as:
byte[] arr = { 49, 49, 49, 49, 49};
InetAddress address = InetAddress.getByName(host);
connection = new Socket(address, port);
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
At receiving end, on the server I have:
byte[] msgType = new byte[5];
in = new BufferedInputStream(connection.getInputStream());
int bytesRead = in.read(msgType, 0, 5);
System.out.println("msg rcvd: " + msgType.toString());
In the output I get weird string:
server: waiting for connection
server: connection received from localhost
server: Connection Successful
bytes read: 5
msg rcvd: ��w
How can make sure I get same bytes as I sent from my client?
I'm not sure exactly what are trying to print out, but I can tell you that msgType.toString() will not print the contents of the byte array.
Here is a link I found to a method which will print out the byte array in a more meaningful fashion.
You're getting the same bytes, it's just a matter of how you interpret them. If you want to see the bytes as a String use this instead:
System.out.println("msg rcvd: " + new String(msgType, "UTF-8"));
Be careful that the bytes you're dealing have the right encoding though (I assumed UTF-8 here). Since you're already ObjectOutputStream though, you could just use its writeUTF() on the server side and ObjectInputStream.readUTF() on the client side.
If you use an ObjectOutputStream on one side, you'll have to use an ObjectInputStream at the other side.
In your case, a simple OutputStream (maybe buffered) and .write() and .read() will do.
But for printing, don't use byte[].toString(), use Arrays.toString() if you want to have a formatted output.
Edit: I just see you are not even writing your array on the sending side. So you are actually only reading the ObjectOutputStream header.
From the comment:
I am handling server side and I am told that I would be send a byte array. How
do I receive and print that byte array ? byte array in this case is bytes of text/strings
This sounds like the server sends something like simply the Strings encoded in some encoding, like ASCII, UTF-8 or ISO-8859-1. If so, on the receiving end you can use something like this:
String encoding = "UTF-8";
BufferedReader in =
new BufferedReader(new InputStreamReader(connection.getInputStream(),
encoding));
String line;
while((line = in.readLine()) != null) {
System.out.println(line);
}
Of course, make sure the encoding is the same encoding as actually used on the sending side.
The corresponding sending code could be something like this:
String encoding = "UTF-8";
Writer w =
new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(),
encoding));
w.write("Hello World!\n");
w.write("And another line.\n");
w.flush();