How to receive multiple POST requests from same client on the server - java

I am trying to write a java server and client such that the client sends the server a POST request with some xml string read from a file as payload, the server fetches the request from the client and sends it an acknowledgment, and this process repeats till all the xml strings that the client has have been sent (as separate POST requests).
I have made the code for 1 single exchange of request and response between the client and server. But I am unable to extend it for multiple requests from the same client because the client waits for server's response and the server's response is not sent to the client till I write wr.close() or socket.close() after writing bytes in the DataOutputStream object. But as soon as I write either of the two commands, my connection between the server and client closes and the client needs to establish connection all over again in order to send the second request.
This is my server side function that receives the request and sends the response:
public HTTPServer(int port) {
try {
private ServerSocket server = new ServerSocket(port);
private Socket socket = server.accept();
int ind = 0;
while (ind<19) {
//socket is an instance of Socket
InputStream is = socket.getInputStream();
InputStreamReader isReader = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isReader);
//code to read and print headers
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
ind++;
//send response to the client
Date today = new Date();
String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
DataOutputStream wr = new DataOutputStream(socket.getOutputStream());
wr.writeBytes(httpResponse);
wr.flush();
}
socket.close(); // or wr.close()
} catch (IOException i) {
System.out.println(i);
}
}
This is my client side code:
public void postMessage() throws IOException {
// string to read message from input
File folder = new File("path/to/my/files");
String[] listOfFiles = folder.list();
for (int i = 0; i < listOfFiles.length; i++) {
File file = new File(listOfFiles[i]);
Scanner sc = null;
try {
sc = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
final URL url = new URL("http://localhost:8080");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
// Send post request
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
String line = "";
while (sc.hasNextLine()) {
line += sc.nextLine();
line += '\n';
}
wr.writeBytes(line);
wr.flush();
wr.close();
// read response
BufferedReader in;
if (200 <= conn.getResponseCode() && conn.getResponseCode() <= 299) {
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
in = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
String str;
while ((str = in.readLine()) != null) {
System.out.println(str);
}
}
}
Unless I write socket.close() or wr.close() after wr.flush(), my response is not sent to the client and the client keeps waiting for it, but as soon as I do, the server socket is closed and the code terminates. How can I send response to my client without having to close the socket?
EDIT:
This is updated HTTP Client code, which uses sockets to send HTTP request, but the error persists.
public static void main(String[] args) throws Exception {
InetAddress addr = InetAddress.getByName("localhost");
Socket socket = new Socket(addr, 8080);
boolean autoflush = true;
// string to read message from input
File folder = new File("/Users/prachisingh/IdeaProjects/requests_responses");
String[] listOfFiles = folder.list();
for (int i = 0; i < listOfFiles.length; i++) {
System.out.println("File " + listOfFiles[i]);
File file = new File("/Users/prachisingh/IdeaProjects/requests_responses/" + listOfFiles[i]);
Scanner sc = null;
try {
sc = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String line = "";
while (sc.hasNextLine()) {
line += sc.nextLine();
line += '\n';
}
PrintWriter out = new PrintWriter(socket.getOutputStream(), autoflush);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// send an HTTP request to the web server
out.println("POST / HTTP/1.1");
out.println("Host: http://localhost:8080");
out.println(line);
out.println();
// read the response
boolean loop = true;
StringBuilder sb = new StringBuilder(8096);
while (loop) {
if (in.ready()) {
int r = 0;
while (r != -1) {
r = in.read();
sb.append((char) r);
}
loop = false;
}
}
System.out.println(sb.toString());
}
socket.close();
}

Related

exchange both string and binary data using socket without closing it

i'm working on an instant messaging project which it's client side is android and server is java
i need to use socket with streams
here is my protocol (something like HTTP) :
Method : attachment \n
Content-Length : {some-int-value} \n
\r\n
binary data bla bla bla...
lets assume i want to send this message from client to server
by doing so exchanging header section goes pretty well
but reading binary data at the server side never complete and server goes into hang for good
Client side code :
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(SERVER_ADDRESS, SERVER_PORT);
try {
socket.connect(address);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
byte[] data = getSomeBinaryData();
writer.write("Method : attachment" + "\n");
writer.write("Content-Length : " + data.length + "\n");
writer.write("\r\n");
writer.flush();
out.write(data); // write binary data
// do more exchange later
} catch (IOException ex) {
// handle exception
}
Server starter code :
public static void main(String[] args){
ExecutorService pool = Executors.newFixedThreadPool(50);
try (ServerSocket server = new ServerSocket(PORT_NUMBER)) {
while (true) {
try {
Socket connection = server.accept();
Callable<Void> task = new ClientTask(connection);
pool.submit(task);
} catch (IOException ex) {}
}
} catch (IOException ex) {
System.err.println("Couldn't start server");
}
}
Server Task thread for each client :
class ClientTask implements Callable<Void> {
private Socket connection;
private HashMap<String, String> header = new HashMap<>();
private byte[] content;
ClientTask(Socket c) {
this.connection = c;
}
#Override
public Void call() throws Exception {
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
readHeader(reader);
System.out.println("incoming message : " + header.get("Method"));
int contentLength = Integer.parseInt(header.get("Content-Length"));
content = new byte[contentLength];
int bytesRead = in.read(content, 0, contentLength);
System.out.print(bytesRead);
return null;
}
private void readHeader(BufferedReader reader){
try {
char c;
StringBuilder builder = new StringBuilder();
while ((c = (char) reader.read()) != '\r'){
if(c == '\n'){
String line = builder.toString();
line = line.replaceAll(" ", "");
String[] sections = line.split(":");
header.put(sections[0], sections[1]);
builder = new StringBuilder(); // clear builder
}else {
builder.append(c);
}
}
reader.read(); // skip the last \n character after header
} catch (IOException e) {
e.printStackTrace();
}
}
As James said a clue I wanted to share the solution
maybe it help someone with similar issue
in the call method of ClientTask class i should use this code :
#Override
public Void call() throws Exception {
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
readHeader(reader);
System.out.println("incoming message : " + header.get("Method"));
// read binary Content
int bytesRead = 0;
int bytesToRead = Integer.parseInt(header.get("Content-Length"));
content = new byte[bytesToRead];
while (bytesRead < bytesToRead) {
int result = in.read(content, bytesRead, bytesToRead - bytesRead);
if (result == -1)
break; // end of stream
bytesRead += result;
}
return null;
}

Java Client Server

I am trying to pass message from server to client in terminal. What I would like the program to do is, in the client, it should be able to enter a command, get response from server, and be able to enter another command without restarting Client (by java Client).
Client.java
Socket socket = new Socket(host, port);
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String response = "";
boolean continuation = true;
while(continuation) {
Scanner input = new Scanner(System.in);
String command = (input.nextLine()).toString();
bw.write(command+"\r\n");
bw.flush();
if(command.equals("cmd1") {
while ((response = br.readLine()) != null) {
System.out.println(response);
}
}
System.out.println("This line will not execute as well.");
}
Server.java
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
String[] in = br.readLine().split("\\s+");
String command = in[0];
if(command.equals("cmd1")) {
String response = "";
response = response + "RESPONSE:\r\n";
response = response + "This is a response.\r\n";
bw.write(response);
bw.flush();
}
If I don't put while((response = br.readLine()!= null) { ... } in Client.java, it is possible to enter multiple inputs in the terminal, but if I put it, it prints the response from the server and another input cannot be done without restarting Client.
Any help would be appreciated.
Thanks
This should work:
server:
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
boolean continuation = true;
while (continuation) {
String command = dis.readUTF();
//proceeed command
dos.writeUTF("response");
dos.flush();
}
Client:
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF("your command");
while (dis.available() == 0) {
try {
//wait for response
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(RandomTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
String response = dis.readUTF();
//and so on

Java Socket - send many message

I have two simple classes:
Client:
public static void main(String[] args) throws IOException {
InetAddress addr = InetAddress.getByName(null);
Socket socket = null;
try {
socket = new Socket(addr, 1050);
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
in = new BufferedReader(isr);
OutputStreamWriter osw = new OutputStreamWriter( socket.getOutputStream());
BufferedWriter bw = new BufferedWriter(osw);
out = new PrintWriter(bw, false);
stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput;
// read user input
while (true) {
userInput = stdIn.readLine();
System.out.println("Send: " + userInput);
out.println(userInput);
out.flush();
String line = in.readLine();
while(line != null){
System.out.println(line);
line = in.readLine();
}
System.out.println("END");
}
}
catch (UnknownHostException e) {
// ...
} catch (IOException e) {
// ...
}
// close
out.close();
stdIn.close();
socket.close();
}
Server:
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter out = new PrintWriter(bw, /*autoflush*/true);
private void sendMessage(String msg1, String msg2) {
out.println(msg1);
// empy row
out.println("");
out.println(msg2);
}
The user enters a message, and this is sent to the server. Then, the server responds with N messages.
After the first request, the client stops and is never printed the word "END".
How do I send multiple messages at different times, with only one socket connection?
Firstly, you don't need to send an empty row, because you are sending by "line" and recieving by "line".
out.println(msg1);
out.println(msg2);
and
userInput = stdIn.readLine();
Here, userInput will only equal msg1
What I would recommend, would be not to loop on stdIn.readLine() = null, but have the client send, for example, "END_MSG", to notify the server that it will not send anymore messages.
Perhaps something like...
SERVER:
userInput =stdIn.readLine();
if(userInput.Equals("START_MSG");
boolean reading=true;
while(reading)
{
userInput=stdIn.readLine();
if(userInput.Equals("END_MSG")
{
//END LOOP!
reading = false;
}
else
{
//You have received a msg - do what you want here
}
}
EDIT:CLIENT:
private void sendMessage(String msg1, String msg2) {
out.println("START_MSG");
out.println(msg1);
out.println(msg2);
out.println("END_MSG");
}
(It also looks like in your question to have mixed up the client and the server?)

After requesting 2nd http GET command to get 2nd range, couldn't get any response

I am trying to get whole txt file range by range which is specificly determined. 1st request is successfully completed but when I do second get request to receive the second part, I couldn't get any response, just nulls. Is there a lack of something? I put a while loop to observe if any value will come after nulls, but I couldn't see!
I don't use any special library for this http socket. I just create a socket with port 80 and a bufferedwriter(writer) and bufferedreader(reader) to communicate with server.
This is the whole method. I have updated the question:
public static void rangedRequest(String host, String url, int totalPartNum, String outputFile) throws IOException{
String headRequest = "HEAD " +url+" HTTP/1.1\r\n"
+ "Host: "+ host +"\r\n\r\n";
Socket sock = null;
BufferedWriter writer = null;
BufferedReader reader = null;
try {
sock = new Socket(host, 80);
writer= new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
reader= new BufferedReader(new InputStreamReader(sock.getInputStream()));
} catch (UnknownHostException ex) {
System.out.println("ERROR:Unknown host");
System.exit(0);
}
writer.write(headRequest);
writer.flush();
/***************Response**************/
String response;
int totalLength = 0;
do{
response = reader.readLine();
if(response.indexOf("Content-Length") > -1){
totalLength = Integer.parseInt(response.substring(response.indexOf(' ')+1));
response = null;
}
}while(response != null);
/****File Length infor is received****/
BufferedWriter output = new BufferedWriter(new FileWriter(outputFile));
int range = totalLength/totalPartNum;
for (int i = 0; i < totalPartNum; i++) {
String getRequest = "GET " + url + " HTTP/1.1\r\n" +
"Host: "+ host + "\r\n" +
"Range: bytes="+ i*range + "-" + ((i+1)*range -1) +
"\r\n\r\n"; //get range query
writer.write(getRequest);
writer.flush();
boolean afterInfo = false;
while(!reader.ready()){}
do{
response = reader.readLine();
if(response.indexOf("Range")>-1){ //After some information, there is an empty line and data
afterInfo = true; //To understand info part is reached
}
}while(!(response.length() < 1 && afterInfo));
while(response != null){
output.write(response);
response = reader.readLine();
}
}
sock.close();
}
Create new socket, each time you are sending a new request to the Http server. So that you need to reconstruct sock, writer and reader then do the request to the Http server and finally close the socket and shutdown its input and output streams in the loop.

Socket in Android remains stuck

I have a server written in C# and a client side in Android. If I send a message from client (Android) to server (c#) and from server to client, everything works fine. If I try to send one message from client , one from server, another from client, the client remains stuck at reading the message from the server. What could be the problem?
My client code is:
sendBytes("HELLOX".getBytes());
readBytes(byDataReceived);//here it gets stucked
...
try
{
int nrsend=sendBytes("HELLOX".getBytes());
readBytes(byDataReceived);
}
catch (Exception se)
{
Log.d("IdealLog","Exception: "+se.getMessage()+" ");
Toast.makeText(context, se.getMessage()+" " , 10000).show();
// MessageBox.Show(se.Message);
return false;
}
...
public static int readBytes(byte[] myByteArray) throws IOException
{
Log.d("IdealLog","readBytes-begin");
InputStream in = socket.getInputStream();
BufferedReader buffreader = new BufferedReader(new InputStreamReader(in));
String finalText = "";
String text = "";
while ((text = buffreader.readLine()) != null)
{
finalText += text;
}
myByteArray=new byte[myByteArray.length];
myByteArray=EncodingUtils.getAsciiBytes(finalText);
Log.d("IdealLog","Input Stream: "+finalText);
Log.d("IdealLog","TEST: "+EncodingUtils.getAsciiString(myByteArray));
Log.d("IdealLog","readBytes-end");
byDataReceived=myByteArray;
buffreader.close();
return myByteArray.length;//myByteArray.length;
}//readBytes end
public static int sendBytes(byte[] myByteArray) throws IOException
{
return sendBytes(myByteArray, 0, myByteArray.length);
}//sendBytes end
public static int sendBytes(byte[] myByteArray, int start, int len) throws IOException
{
if (len < 0)
{
throw new IllegalArgumentException("Negative length not allowed");
}
if (start < 0 || start >= myByteArray.length)
{
throw new IndexOutOfBoundsException("Out of bounds: " + start);
}
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
// dos.writeInt(len);
if (len > 0)
{
dos.write(myByteArray, start, len);
}
int size=dos.size();
dos.flush();
return size;
}//sendBytes end
My server code:
static void Main(string[] args)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 1408);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ip);
socket.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = socket.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);
string welcome = "HELLO&";
byte[] data = new byte[200];
client.Receive(data);
Console.WriteLine("Received data from CLIENT TEST1: {0}", System.Text.ASCIIEncoding.ASCII.GetString(data));
ASCIIEncoding asen = new ASCIIEncoding();
byte[] data2 = new byte[200];
data2 = asen.GetBytes(welcome);
client.Send(data2, data2.Length, SocketFlags.None);
//if i comment out from this 3 lines, everything is working fine
byte[] data3 = new byte[200];//this
client.Receive(data3);//this
Console.WriteLine("Received data from CLIENT TEST2: {0}", System.Text.ASCIIEncoding.ASCII.GetString(data3));//this
Console.WriteLine("Disconnected from {0}", clientep.Address);
client.Close();
socket.Close();
Console.ReadLine();
}
Modify into this:
//if i comment out from this 3 lines, everything is working fine
byte[] data3 = new byte[200];//this
client.Receive(data3);//this
Console.WriteLine("Received data from CLIENT TEST2: {0}", System.Text.ASCIIEncoding.ASCII.GetString(data3));//this
client.Send(data2, data2.Length, SocketFlags.None);
Console.WriteLine("Disconnected from {0}", clientep.Address);
client.Close();
socket.Close();
Console.ReadLine();
}

Categories