TCP: How to get response from Vb.net server in Android Client? - java

This is not a possible duplicate. No answer on this site adequately answers or solves my issue.
I am trying to connect to a VB.NET server via TCP socket and get response in Android application. The response is always null as string or -1 as bytes.
I have to connect and get a response for multiple platforms but for the moment I just want to focus on the Android app. Maybe if I figure it out, it will be easier to move forward to other platforms.
I do not have access to edit any code in the VB.NET live server. There system is pretty old and has been only sending responses to other Windows clients up until now.
Here is my Android client. It is inside a background task which is called from the mainActivity. The below command string should return coordinates in the form of a string from the server. Nothing is returned.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void sendMessage() throws IOException, InterruptedException {
Socket socket = null;
String host = "";
int port = ;
PrintStream stream = null;
String command="";
try {
Socket s = new Socket(host,port);
System.out.println("Socket created");
//outgoing stream redirect to socket
OutputStream out = s.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println(command);
output.flush();
System.out.println("command sent");
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
//read line(s)
System.out.println("Getting response:");
String st = input.readLine();
System.out.println("Response : " + st);
//Close connection
s.close();
}
catch (UnknownHostException e) {
System.out.println("Don't know about host : " + host);
e.printStackTrace();
System.exit(1);
}
catch (IOException e) {
System.out.println("Couldn't get I/O for the connection to : " + host);
e.printStackTrace();
System.exit(1);
}
}
}
A developer also sent me a test client in VB which connects, sends and recieves without problem
Here is a class of a VB:NET Dummy server project the developer has sent me to see how the live server is setup code-wise. I can see it gets the string as unicode but I am not confident in VB to know where my Java code is going wrong.
When I open the project and start the server on localhost I cant connect to it from the java client anyway. Then I have written another client in PHP, same problem, connection established but no response. I downloaded a socket tester software but it also can connect but does not get a response.
Option Explicit On
Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports Microsoft.VisualBasic
Imports System.Net.Dns
Imports System.Text.UnicodeEncoding
Imports System.Threading
Imports System.Data.SqlClient
Public Enum glenConnectionType
ConstantConnection = 1
ConnectOnDemand = 2
AsyncConnection = 3
End Enum
Public Class clsDynaListner
Public tcpServer As Socket
Public tcpClient As Socket
Public tcpPort As Integer
Public tcpBilnr As Integer ' was shared SHOULD PROB BE INITIALISED TO 0
Public ThreadClient As Thread
Public LastKontakt As Date = Nothing
Public ConActive As Boolean = False
Private tcpClientEndPoint As System.Net.IPEndPoint
Private bCommandLength(15), bReplyLength(15) As Byte
Private iCommandLength, iReplyLength As Integer
Private sReplyLength As String
Private sCommand, sReply As String
Private theCommandBytes() As Byte
Private theReplyBytes() As Byte
Private Const AsyncMaxBytes As Integer = 600000 '1024
Public Shared AsyncData As String = Nothing
Public Sub New(ByVal currentTCPPort As Integer, ByVal theConnectionType As glenConnectionType)
tcpPort = currentTCPPort
tcpClientEndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, tcpPort)
'Select Case theConnectionType
' Case glenConnectionType.ConstantConnection
' ThreadClient = New Threading.Thread(AddressOf ListenForConstantConnection)
' Case glenConnectionType.ConnectOnDemand
ThreadClient = New Threading.Thread(AddressOf ListenForConnectOnDemand)
' Case glenConnectionType.AsyncConnection
'ThreadClient = New Threading.Thread(AddressOf ListenForAsyncConnection)
'End Select
ThreadClient.Start()
End Sub
Private Sub ListenForConnectOnDemand()
While (True)
Try
tcpServer = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
tcpServer.SendBufferSize = TCP_BUFFER_SIZE
tcpServer.ReceiveBufferSize = TCP_BUFFER_SIZE
tcpServer.Blocking = True
tcpServer.Bind(tcpClientEndPoint)
tcpServer.Listen(0)
tcpClient = tcpServer.Accept
tcpClient.SendBufferSize = TCP_BUFFER_SIZE
tcpClient.ReceiveBufferSize = TCP_BUFFER_SIZE
' Find out how big the command is going to be
tcpClient.Receive(bCommandLength)
iCommandLength = CType(Unicode.GetString(bCommandLength), Integer)
' Bring that command to daddy
Array.Resize(theCommandBytes, iCommandLength + 1)
tcpClient.Receive(theCommandBytes)
sCommand = Unicode.GetString(theCommandBytes)
gInMessage = sCommand
' Get the reply
sReply = "Response:"
gOutMessage = sReply
' Inform the controller of the length of the reply transmission
iReplyLength = (sReply.Length * 2) - 1
sReplyLength = iReplyLength.ToString.PadLeft(8, "0")
bReplyLength = Unicode.GetBytes(sReplyLength)
tcpClient.Send(bReplyLength)
' Send the reply data
Array.Resize(theReplyBytes, iReplyLength + 1)
theReplyBytes = Unicode.GetBytes(sReply)
tcpClient.Send(theReplyBytes)
Array.Clear(theCommandBytes, 0, theCommandBytes.Length)
Array.Clear(theReplyBytes, 0, theReplyBytes.Length)
tcpClient.Close()
tcpServer.Close()
tcpClient = Nothing
tcpServer = Nothing
Catch ex1 As Exception
Try
tcpClient.Close()
tcpServer.Close()
tcpClient = Nothing
tcpServer = Nothing
' ErrMessage = "LisForContr :" & tcpPort.ToString & ex1.Message
Catch
End Try
End Try
End While
End Sub
Protected Overrides Sub Finalize()
Try
tcpServer.Close()
ThreadClient.Abort()
Catch
End Try
MyBase.Finalize()
End Sub
End Class
I have been working with this for a while. The apps I have built are complete for PHP Web App, Android Native, and iPhone Native. The problem is only getting the response from the VB server.
Would like some help to push me in the right direction.
Also I enquired with the developers if the response has a line-break. It does not and it does seem they are willing to mess with the code as it served there purpose for many many years. So I have to find away around that.
If you need me to provide more info just ask.

To send to a VB.NET server from Java you must send the string as unicoded bytes. Send the length at the bytes to expect first and then send the primary data and flush. You have to know exactly what the server is expecting in order to format and encode the data accordingly in preparation to send it.
I was able to successfully fix my issue after debugging VB client and server. This client will process byte arrays, stream advanced sql commands and get the response. The update will be getting xml table data. Anyone who wants to input how to make this client better. You are welcome.
Updated my java client as follows.
/**
* MR-TCP Java & VB.NET DataExchange Client 0.95 - Maze Runner 2015
*/
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Client {
public static String sendCommand(String commandString, Boolean IsID) throws IOException, InterruptedException {
String host;
int port;
String command;
byte[] commandBytes;
String commandLength;
byte[] cmdLengthBytes;
Socket s;
DataOutputStream stream;
String dataString = "";
host = ""; //
port = 0; //
command = commandString;
commandBytes = command.getBytes("UTF-16LE"); // returns byte[18]
if(IsID){
commandLength = "00000021";
cmdLengthBytes = commandLength.getBytes("UTF-16LE");
} else {
String iCommandLength = command; // Get the command length
cmdLengthBytes = iCommandLength.getBytes("UTF-16LE");
int commandNewLength = cmdLengthBytes.length-1;
String newLength = "0000" + String.valueOf(commandNewLength);
cmdLengthBytes = newLength.getBytes("UTF-16LE");
}
try {
s = new Socket(host, port); // Connect to server
//Send the command to the server
stream = new DataOutputStream(s.getOutputStream()); // get ready to send
stream.write(cmdLengthBytes); // tell the server how many bytes to expect
System.out.println("Command length sent");
stream.write(commandBytes); // Send the command to papa...
stream.flush(); // guaranteed sending
System.out.println("Command sent");
//Receive the command from the server.
DataInputStream is = new DataInputStream(s.getInputStream()); // get ready to receive
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); // prepare to get array
int nRead;
byte[] data = new byte[1024];
while ((nRead = is.read(data, 0, data.length)) != -1) { // read the array byte by byte
buffer.write(data, 0, nRead);
}
byte[] dataBytes = buffer.toByteArray(); // get complete array
dataString = buffer.toString("UTF-16LE").substring(8); // get rid of the array length and convert to string
stream.close(); // close the dataStream
s.close(); // close the connection
System.out.println("Disconnected");
} catch (IOException e){
e.printStackTrace();
}
System.out.println("Function Complete");
System.out.println("Server response:" + dataString);
return dataString;
}
}

Related

Socket hangs when trying to read input stream from web browser Java

I am attempting to read an input stream from a socket provided by a web browser client. Every approach I have taken has got the same results thus far, it just hangs and I don't know why. I have tried mark() marking the read limit to what is available and still no go.
inputStream.mark(inputStream.available());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 9];
int read;
while((read = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, read);
}
byte[] bytes = outputStream.toByteArray();
I have also tried clientSocket.shutdownInput() to tried to fix this issue, still no good.
Here is my attempt below:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class Server {
public static void main(String[] args)
{
ServerSocket server = null;
try {
// Server is listening on port 3001
server = new ServerSocket(3001, 1, InetAddress.getByName("localhost"));
server.setReuseAddress(true);
// running infinite loop for getting
// client request
while (true) {
// socket object to receive incoming client
// requests
Socket client = server.accept();
// Displaying that new client is connected
// to Server
System.out.println("New client connected"
+ client.getInetAddress()
.getHostAddress());
// create a new thread object
ClientHandler clientSock
= new ClientHandler(client);
// This thread will handle the client
// separately
new Thread(clientSock).start();
}
}catch (IOException e) {
e.printStackTrace();
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
// Constructor
public ClientHandler(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
public void run() {
InputStream inputStream = null;
OutputStream clientOutput = null;
try {
inputStream = clientSocket.getInputStream();
inputStream.mark(inputStream.available());
clientSocket.shutdownInput();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 9];
int numRead;
while((numRead = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, numRead);
}
byte[] bytes = outputStream.toByteArray();
String payloadString = new String(bytes, StandardCharsets.UTF_8);
System.out.println(payloadString);
clientOutput = clientSocket.getOutputStream();
clientOutput.write(("HTTP/1.1 \r\n" + "200 OK").getBytes());
clientOutput.write(("ContentType: " + "text/html" + "\r\n").getBytes());
clientOutput.write("\r\n".getBytes());
clientOutput.write("Hello World!".getBytes());
clientOutput.write("\r\n\r\n".getBytes());
clientOutput.flush();
inputStream.close();
clientOutput.close();
try{
clientSocket.close();
}catch(Exception ex){
ex.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Any help would be most appreciated! Thank you.
browsers suggests you should toss this all in the garbage and use HTTP, because, well, browsers.
But, if you insist, there are two problems here.
You've made it crazy complicated.
You can take all of that code and replace it all with this simple little line:
byte[] bytes = in.readAllBytes();
That replaces the lines starting with in.mark(in.available()) (this line does nothing at all, I have no idea where you got this from. If you think it is supposed to do something specific, you might want to mention that. Because it doesn't do anything. mark is useful if you ever reset, which you aren't, and you don't need to here, hence, useless), all the way to `byte[] bytes =...;
sockets don't close unless sender goes out of its way to close it
Your read code (yours, or the much simpler one-liner above) reads everything until the stream closes. In your second snippet, you close it right away, which obviously doesn't work. You cannot know when to close it, the sender does this job. Evidently it's not doing it.
I advise you to adapt protocols that pre-roll sizes, so you know how much to read and aren't dependent on closing the socket just to signal that the data is sent.
For example:
byte[] sizeRaw = in.readNBytes(4);
int size = ByteBuffer.wrap(bytes).getInt();
byte[] bytes = in.readNBytes(size);
You will of course have to adjust the sending code to send the size first (as a 32-bit value, big endian). One way or another you have to look at the sending code here. Either fix it so that it closes once done, or, better yet, adjust it so it sends size first.

Java - read register value by OBIS code with TCP client

I have connection to TCP server (ip,port) to which meter is connected. I'd like to read the specified data from this port because when I'm using standard read method it sends me the whole data stream which takes about 15 minutes to read. So my question: is there any method I can use to get one specified register's value using his OBIS code (1.1.1.8.0.255 - active energy taken) in java via TCP server?
import java.net.*;
import java.io.*;
public class scratch {
public static void main(String[] args) {
String hostname = "ip (hidden)";
int port = port (hidden);
try (Socket socket = new Socket(hostname, port)) {
OutputStream out = socket.getOutputStream();
InputStream input = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(input);
int character;
StringBuilder data = new StringBuilder();
String test = "/?!\r\n";
byte[] req = test.getBytes();
out.write(req);
while ((character = reader.read()) != '\n') {
data.append((char) character);
}
System.out.println(data);
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}
The message "test" send initiation request to meter and his respond is correct but I dont' know how to put flags (ACK STX ETX) in my request, I've tried something like this:
String test2 = (char)0x6 + "051\r\n";
byte[] req2 = test2.getBytes("ASCII");
out.write(req2);
But meter doesn't recognize it.

Dart VM service client

I'm trying to get a simple TCP client going that can
connect to the Dart VM service, send a request and get a response.
I've tried it with and without connect().
The other question I have is what's the best Dart command
to "start" the VM service so that it's listening for requests?
With possibly giving what host and port to use, if needed.
Commands like --observe or --enable-vm-service are for the Observatory and I don't need that.
I've been using this
but I'm not sure what host and port it's using by default for that.
dart --pause_isolates_on_start bicycle.dart
So far, after I run the Dart command and run the client,
I get:
Exception: java.net.ConnectException: Connection refused: connect
or it seems to send the request, but it just gets back "-1".
So what Dart command should I be using and what changes do I need to
make to be able to get a response back from the VM service?
I need to be able to do the client in Java and not Dart.
UPDATE:
Is the problem that the Dart VM service is using WebSockets and that
isn't compatible with Java Socket I/O?
It's looking like it does need to connect via a WebSocket, so I'm
looking into trying to get that to build and try it.
Thanks!!
import java.net.Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketAddress;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class DartTest
{
public static void main(String[] args)
{
Socket socket = null;
InetAddress inetAddress = null;
InetSocketAddress inetSocketAddress = null;
OutputStream os = null;
InputStream is = null;
byte[] outBuf;
byte[] inBuf;
byte[] zeroDzeroAspaces = {(byte)0x0d, (byte)0x0a, (byte)0x20, (byte)0x20};
String sZeroDzeroAspaces = new String(zeroDzeroAspaces);
byte[] zeroDzeroA = {(byte)0x0d, (byte)0x0a};
String sZeroDzeroA = new String(zeroDzeroA);
int iAvail;
int iByte;
int iReadBytes;
StringBuffer readSb = new StringBuffer();
String sHost = "127.0.0.1";
int iPort = 8181;
try
{
//inetSocketAddress = new InetSocketAddress(sHost, iPort);
socket = new Socket(sHost, iPort);
//socket = new Socket();
//socket.connect((SocketAddress)inetSocketAddress);
os = socket.getOutputStream();
is = socket.getInputStream();
StringBuffer outSb = new StringBuffer();
outSb.append("{");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("jsonrpc");
outSb.append((char)0x22);
outSb.append(": ");
outSb.append((char)0x22);
outSb.append("2.0");
outSb.append((char)0x22);
outSb.append(",");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("method");
outSb.append((char)0x22);
outSb.append(": ");
outSb.append((char)0x22);
outSb.append("getVersion");
outSb.append((char)0x22);
outSb.append(",");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("params");
outSb.append((char)0x22);
outSb.append(": {},");
outSb.append(sZeroDzeroAspaces);
outSb.append((char)0x22);
outSb.append("id");
outSb.append((char)0x22);
outSb.append(": ");
outSb.append((char)0x22);
outSb.append("1");
outSb.append((char)0x22);
outSb.append(sZeroDzeroA);
outSb.append("}");
//System.out.println("outSb: '"+outSb.toString()+"'");
outBuf = outSb.toString().getBytes();
os.write(outBuf);
os.flush();
while ( true )
{
iByte = is.read();
System.out.println("iByte: "+iByte);
if ( iByte == -1 )
break;
readSb.append((char)iByte);
}
System.out.println("readSb: '"+readSb.toString()+"'");
if ( socket != null )
socket.close();
}
catch (Exception e)
{
System.out.println("Exception: "+e.toString());
}
}
}
Answering my own question:
Using WebSockets was the main thing, trying to connect to
the VM service/Observatory using "regular" Socket TCP
wasn't going to work.
Then the next roadblock came when the WebSocket server handshake
was failing when it would return "200 OK" instead of "101" to "Upgrade".
Then I was looking at the intelliJ plugin code, to see how they connected, and they used "ws://localhost:8181/ws", I was trying to use
"ws://localhost:8181", and once I used that, the handshake went through!!
When it worked I was using:
dart --enable-vm-service --pause_isolates_on_start bicycle.dart
I'm not sure who I'm actually connected to, the Observatory,
or the VM service, but at least I've finally gotten to the point
where I can try to send a request, and possibly get a reply.

Unable to receive String Data from Python Socket to Java Socket

I am having trouble with using sockets
As you can see the codes worked when I tried to send string from JAVA to PYTHON.
But however I am having trouble when I tried to send string from PYTHON to JAVA ,which is the opposite way. And I need it to convert into bytes and decode it since I encoded the string before I send it over.
Thus the problem now is how or is there anything wrong in my codes when I send a string from Python socket and receiving the string by Java Socket?
I really need help, thank you!
Python (SERVER) Codes:
import socket
import ssl
import hashlib
import os
from Crypto.Cipher import AES
import hashlib
from Crypto import Random
sHost = ''
sPort = 1234
def bindSocket():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #IPv4 and TCP
try:
s.bind((sHost,sPort))
print("Socket created and binded")
except socket.error as msgError:
print(msgError)
print("Error in Binding Socket")
return s #so that we can use it
def socketConnect():
s.listen(1) #listen to 1 connection at a time
while True:
try:
conn, address = s.accept() #Accept connection from client
print ("Connected to: " + address[0] + ":" +str(address[1]))
except socket.error as error:
print ("Error: {0}" .format(e))
print ("Unable to start socket")
return conn
def loopCommand(conn):
while True:
passphrase = "Hello Java Client "
data = conn.recv(1024)#receive the message sent by client
print(data)
conn.send(passphrase.encode('utf-8'))
print("Another String is sent to Java")
s = bindSocket()
while True:
try:
conn = socketConnect()
loopCommand(conn)
except:
pass
Java (Client) Codes:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketSTesting {
public Socket socketStartConnect() throws UnknownHostException, IOException {
String ip = "192.168.1.16";
int port = 1234;
Socket clientSocket = new Socket(ip, port);
if (clientSocket.isConnected()) {
System.out.println("It is connected to the server which is " + clientSocket.getInetAddress());
} else if (clientSocket.isClosed()) {
System.out.println("Connection Failed");
}
return clientSocket;
}
public void sendString(String str) throws Exception {
// Get the socket's output stream
Socket socket = socketStartConnect();
OutputStream socketOutput = socket.getOutputStream();
byte[] strBytes = str.getBytes();
// total byte
byte[] totalByteCombine = new byte[strBytes.length];
System.arraycopy(strBytes, 0, totalByteCombine, 0, strBytes.length);
//Send to Python Server
socketOutput.write(totalByteCombine, 0, totalByteCombine.length);
System.out.println("Content sent successfully");
//Receieve Python string
InputStream socketInput = socket.getInputStream();
String messagetype = socketOutput.toString();
System.out.println(messagetype);
}
public static void main(String[] args) throws Exception {
SocketSTesting client = new SocketSTesting();
String str = "Hello Python Server!";
client.sendString(str);
}
}
You seem to think that String messagetype = socketOutput.toString(); performs I/O. It doesn't, so printing it or even calling it does nothing and proves nothing. You need to read from the socket input stream.
BTW clientSocket.isConnected() cannot possibly be false at the point you are testing it. If the connect had failed, an exception would have been thrown. Similarly, clientSocket.isClosed() cannot possibly be true at the point you are testing it, because you haven't closed the socket you just created. Further, if isClosed() was true it would not mean 'connection failed', and isConnected() being false does not entail isClosed() being true. Remove all this.

Basic Java Webserver - Receiving a SocketException: Connection Reset

I've attempted to create a basic HTTP/1.1 compliant web server which supports simple GET requests with persistent connections. I'm getting a SocketException: Connection Reset error occuring at line 61 (if (line==null || line.equals("")). I'm testing it by running it and then directing my chrome browser to localhost portnumber. When I test it with a page with multiple images it seems like only 1 request is being processed before the exception occurs, but I'm not sure what's wrong as this is my first attempt at any kind of socket programming.
Here's my updated Code after removing DataOutputStream:
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.StringTokenizer;
public class webserve
{
public static void main(String[] args) throws Exception
{
String rootPath = "~/Documents/MockWebServerDocument/";
int port = 10000;
if(rootPath.startsWith("~" + File.separator))
{
rootPath = System.getProperty("user.home") + rootPath.substring(1);
}
String requestLine="";
StringTokenizer tokens=null;
String line, command;
Date date = new Date();
String connectionStatus="";
//Create new server socket listening on specified port number
ServerSocket serverSocket = new ServerSocket(port);
while(true)
{
//Wait for a client to connect and make a request
Socket connectionSocket = serverSocket.accept();
System.out.println("Socket opened");
//Input stream from client socket
BufferedReader incomingFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
//PrintWriter to send header to client socket
PrintWriter outgoingHeader = new PrintWriter(connectionSocket.getOutputStream(),true);
//OutputStream to send file data to client socket
ObjectOutputStream outgoingFile = new ObjectOutputStream(connectionSocket.getOutputStream());
//Date format for HTTP Header
SimpleDateFormat HTTPDateFormat = new SimpleDateFormat("EEE MMM d hh:mm:ss zzz yyyy");
//Create a HashMap to store the request header information
HashMap<String,String> requestHeader = new HashMap<String,String>();
while(connectionSocket.isConnected())
{
//requestHeader.clear();
while((line = incomingFromClient.readLine()) != null)
{
if(line.isEmpty())
{
break;
}
//If this is the first line of the request, i.e doesnt contain a colon
if(!(line.contains(":")))
{
requestLine = line;
requestHeader.put("Request", requestLine);
}
else
{
//Otherwise, find the colon in the line and create a key/value pair for the HashMap
int index = line.indexOf(':')+2;
String header = line.substring(0,index-1);
line = line.substring(index).trim();
requestHeader.put(header, line);
System.out.println(header + " " + line);
}
}
connectionStatus = (String)requestHeader.get("Connection:");
requestLine = (String)requestHeader.get("Request");
System.out.println("RequestLine: " + requestLine);
if(!requestLine.equals("")||!(requestLine.equals(null)))
{
tokens = new StringTokenizer(requestLine);
command = tokens.nextToken();
String filename = tokens.nextToken();
filename = cleanUpFilename(filename);
String fullFilepath = rootPath + filename;
System.out.println("Full FilePath: " + fullFilepath);
File file = new File(fullFilepath);
//Get the number of bytes in the file
int numOfBytes=(int)file.length();
//Open a file input stream using the full file pathname
FileInputStream inFile = new FileInputStream(fullFilepath);
//Create byte array to hold file contents
byte[] fileInBytes = new byte[numOfBytes];
inFile.read(fileInBytes,0,numOfBytes);
inFile.close();
//Write the header to the output stream
outgoingHeader.print("HTTP/1.1 200 OK\r\n");
outgoingHeader.print("Date: " + HTTPDateFormat.format(date)+"\r\n");
outgoingHeader.print("Server: BC-Server\r\n");
outgoingHeader.print("Last-Modified: " + HTTPDateFormat.format(file.lastModified())+"\r\n");
outgoingHeader.print("Connection: keep-alive\r\n");
outgoingHeader.print("Content-Length: " + numOfBytes);
outgoingHeader.print("\r\n\r\n");
//When the header has been printed, write the byte array containing the file
//to the output stream
outgoingFile.writeObject(fileInBytes);
if(!(connectionStatus.equals("keep-alive")))
{
System.out.println("Closing: " + connectionStatus);
outgoingHeader.close();
outgoingFile.close();
break;
}
else
continue;
}
}
}
}
public static String cleanUpFilename(String filename)
{
//If there is a "/" at the start of the filename, then remove it
if(filename.charAt(0) == '/')
{
filename = filename.substring(1);
}
//If we are given an absolute URI request, strip all characters
//before the third "/"
if(filename.startsWith("http://"));
{
try
{
URI httpAddress = new URI(filename);
//Get the path from the supplied absolute URI, that is remove
//all character before the third "/"
filename = httpAddress.getPath();
//Again, we may have to trim this modified address if there is an
//extra "/" at the start of the filename
if(filename.charAt(0) == '/')
{
filename = filename.substring(1);
}
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
}
return filename;
}
}
Here's my error trace:
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:185)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:282)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:324)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:153)
at java.io.BufferedReader.readLine(BufferedReader.java:316)
at java.io.BufferedReader.readLine(BufferedReader.java:379)
at webserve.main(webserve.java:61)
Any help would be much appreciated, as I'm at a total loss.
Try testing the connection using telnet, wget or curl instead of chrome, because you can then be in control of both sided of the TCP/IP connection.
I think that your web-client is closing the connection from it's side, and you try to read from that socket again (yes, even isConnected() will throw this error when the remote party closed the connection). I am also sorry to say that there is no easy way to combat this other than to catch the exception and handle it gracefully.
This is a problem that often happens with synchronous sockets. Try using java.nio channels and selectors instead.
Using multiple output streams at the same time is highly problematic. In this case you shouldn't create the ObjectOutputStream until you are certain you are going to write an object and you have already written and flushed the headers, because ObjectOutputStream writes a header to the output, which in your present code will appear before any headers, probably causing the client to barf.
In general, SocketException: Connection Reset usually means that you have written to a connection that has already been closed by the peer. As in this case the peer is the client and the client is a Web browser, it can mean anything at all, e.g. the user stopped loading the page, he browsed away, exited the browser, closed the tab. It's not your problem. Just close the socket and forget about it.
For the same reason, your server should also set a reasonable read timeout, like say 10-30 seconds, and bail out if it fires.
The most obvious problem of your server is that it's not multi-threaded. After re-reading your description of the problem, that seems to the be root cause. You need one thread per connection. After serverSocket.accept(), create a new thread to handle the connectionSocket.
while(true)
{
//Wait for a client to connect and make a request
Socket connectionSocket = serverSocket.accept();
new Thread()
{
public void run()
{
//Input stream from client socket
BufferedReader incomingFromClient = ...
etc
}
}.start();
You cannot use DataOutputStream, it's for Java-Java communication. Try Writer for writing headers, and original OutputStream for writing file content.
What's happening is that the browser sees invalid response, and closes the connection. The serve is still writing to the client, which responds RST because the connection is gone.

Categories