This question already has answers here:
Java send udp packet to dns server
(1 answer)
Making a DNS request using Java and timing the response
(3 answers)
DNS query in Java
(4 answers)
Closed last month.
I am trying to get a data response using a socket. I need any kind of response from the DNS. So I try requesting the IP of "www.youtube.com" from google DNS. I am not getting any response.
Network network = ...
String DNS = "8.8.8.8";
try (Socket socket = network.getSocketFactory().createSocket(DNS, 53)) {
socket.connect(new InetSocketAddress("www.youtube.com", 80));
InputStreamReader input = new InputStreamReader(socket.getInputStream());
BufferedReader reader = new BufferedReader(input);
socket.getOutputStream().write("www.youtube.com".getBytes());
String skip = reader.readLine(), string = reader.readLine();
Log.e("READ", skip + " " + string);
} catch (IOException exception) {
String message = context.getText(R.string.nointernet) + ": " +
exception.getLocalizedMessage();
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
context.getVariables().setNetwork(null);
}
In this case, the log is always printing null which means I haven't communicated with the DNS server.
How can a make the socket request?
Related
I want to use android's VpnService to capture packets filter them based off IP address. I can get the packets from the "tun" interface just fine but after that i'm not sure how to forward them to their original destination. Based off of the comments from this answer it seems like i just need to:
Create a new socket to the destination IP address and port
Trim the IP and TCP header to send only the data
Re-attach the IP and TCP header when i get a response
Send the complete packet to the output stream
I have tried to send the data like this:
Socket socket = new Socket();
socket.bind(new InetSocketAddress(0));
if (protect(socket)){
Log.e(TAG, "Socket protected");
}else{
Log.e(TAG, "Socket NOT protected");
}
socket.connect(new InetSocketAddress(ipPacket.getDestinationIp(), ipPacket.getDstPort()));
Log.e(TAG, "Socket connected: " + socket.isConnected());
socket.getOutputStream().write(getTCPHeader(getIpHeader(packet)[1])[1].array());
The methods getTCPHeader(ByteArray packet) and getIpHeader(ByteArray packet) simply splits the packet into two ByteArray's as follows:
private ByteBuffer[] getIpHeader(ByteBuffer packet){
packet.position(0);
ByteBuffer ipHeader = ByteBuffer.allocate(20);
ByteBuffer data = ByteBuffer.allocate(packet.limit() - 20);
packet.get(ipHeader.array(), 0, 20);
packet.get(data.array(), 0, packet.limit() - 20);
return new ByteBuffer[]{ipHeader, data};
}
private ByteBuffer[] getTCPHeader(ByteBuffer packet){
packet.position(20);
ByteBuffer tcpHeader = ByteBuffer.allocate(20);
ByteBuffer data = ByteBuffer.allocate(packet.limit() - 20);
packet.get(tcpHeader.array(), 0, 20);
packet.get(data.array(), 0, packet.limit() - 40);
return new ByteBuffer[]{tcpHeader, data};
}
Now to get a response from the server, i am using the following code:
ByteBuffer responsePacket = ByteBuffer.allocate(65535);
InputStream socketInputStream = socket.getInputStream();
try{
int responseLength = socketInputStream.read(responsePacket.array());
if (responseLength > 20){
Log.e(TAG, "===Server Response===");
Log.e(TAG, "Length: " + responseLength);
ByteBuffer trimmedResponseData = ByteBuffer.allocate(responseLength);
System.arraycopy(responseData.array(), 0, trimmedResponseData.array(), 0, responseLength);
String resp = "";
for (int i = 0; i < responseLength; i++){
resp += String.valueOf(responseData.get(i) + " ");
}
Log.e(TAG, "Response data: " + resp);
ByteBuffer finalPacket = ByteBuffer.allocate(40 + responseLength);
ByteBuffer swappedIpHeader = swapSrcDstAddress(getIpHeader(packet)[0]);
ByteBuffer swappedTcpHeader = swapTCPSrcDst(getTCPHeader(getIpHeader(packet)[1])[0]);
finalPacket.put(swappedIpHeader.array());
finalPacket.put(swappedTcpHeader.array());
finalPacket.put(serverResponseData.array());
Packet finPack = debugPacket(finalPacket);
Log.e("VPN", "Final packet --> Packet size: " + finPack.getTotalLength() + " from " + finPack.getSourceIp() + " src port: " + finPack.getSrcPort() + " going to " + finPack.getDestinationIp() + " dst port: " + finPack.getDstPort());
out.write(finalPacket.array());
}
}catch (Exception e){
//Log.e(TAG, "EXCEPTION: " + e);
e.printStackTrace();
}
This code seems to work either EXTREMELY slowly, or not at all. Sometimes if i go to www.google.com it will load slowly but most of the time it doesn't. Also some times i am getting the following error on the line int responseLength = socketInputStream.read(serverResponse.array());
java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
What is causing this error, and how can i properly forward these packets to the appropriate destination? Any help is greatly appreciated!
What is causing this error?
recvfrom failed exception means that Server has closed the client socket but client was still reading input data (in your case serverResponse.array(). For details, see this.
how can i properly forward these packets to the appropriate
destination?
There is a sample-code from google-sources here that forwards available packets. Please go through the code and the relevant comments. According to google-sources:
This application consists of an Android client and a sample
implementation of a server. It performs IP over UDP and is capable of
doing seamless handover between different networks as long as it
receives the same VPN parameters.It shows how to build a VPN client
using the VpnService class introduced in API level 14.
The sample code of the server-side implementation is Linux-specific
and is available in the server directory. To run the server or port
it to another platform, please see comments in the code for the
details.
one more helpful app link here
I have a program that includes HTTP connection to a PLM application that runs on SQL Server. The program is scheduled to run daily. It collects data from few sources, then issues a query to the PLM to store the data, and finally reads the PLM's reply to verify if the data was properly stored.
The application ran OK, until we upgraded both the DB (into SQL Server 2012) and the PLM.
Since then the upgrade, when the program establishes the connection it receives OK status; however, the data setting query does not affect the data base, and there is no answer received. There are no error messages - just malfunction.
My major question is - how to debug it. I know whet I send and what I receive. How can I get more data on what happens in between?
I attach the code for review. What I didn't add here is the query itself, which is WML-like string. The PLM should fire an answer regardless the query it receives, even if it is an error message. However, I get only NULL.
public Boolean amlArasCommunication (String data , int targetDbType, String passWord)
{
final String url = "http://plm-srv/InnovatorServer/Server/InnovatorServer2012.aspx";
final String schemeUrl = "'http://schemas.xmlsoap.org/soap/envelope/'";
String answer =””;
String dataBase = data base name;
Writer wout;
HttpURLConnection amlConnection = null;
try
{
// instantiate the HttpURLConnection with the URL object - A new connection is
// opened every time by calling the openConnection method of the protocol
// handler for this URL. This is the point where the connection is opened.
amlConnection = (HttpURLConnection) new URL(url).openConnection();
amlConnection.setDoOutput(true);
amlConnection.setDoInput(true);
amlConnection.setRequestMethod("POST");
amlConnection.setRequestProperty("SOAPAction", "ApplyAML");
amlConnection.setConnectTimeout(10000);
amlConnection.setReadTimeout(10000);
amlConnection.setRequestProperty("AUTHUSER", "Admin");
amlConnection.setRequestProperty("AUTHPASSWORD", calcMD5(passWord));
amlConnection.setRequestProperty("DATABASE", dataBase);
String query = "<?xml version='1.0'?>\r\n" +
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=" + schemeUrl + ">\r\n" +
" <SOAP-ENV:Body>\r\n" +
data +
" </SOAP-ENV:Body>\r\n" +
"</SOAP-ENV:Envelope>\r\n";
// instantiate OutputStreamWriter using the output stream, returned from getOutputStream, that writes
// to this connection. If an I/O error occurs while creating the output stream, IOException will be fired.
wout = new OutputStreamWriter(amlConnection.getOutputStream());
wout.write (query);
wout.close();
// At this point, we've sent all the data. The outputStream was closed, while the connection is still open
int result;
if ((result = amlConnection.getResponseCode()) == HttpURLConnection.HTTP_OK)
{
// Get the communication results from the PLM
InputStream ac = amlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader (ac);
BufferedReader in = new BufferedReader(isr);
String readResult = in.readLine ();
int count = 0;
while (readResult != null)
{
answer += readResult + "\n";
readResult = in.readLine ();
count++;
}
in.close();
if (answer.contains("fault"))
System.out.println ("Error message: " + answer + "\nQuery: " + query);
else
log.message ("Lines count=" + count + "; com status=" + result + "; reply: " + answer, false);
}
else
// Error code is returned, or no status code is returned, do stuff in the else block
System.out.println("Connection failed with the following code: " + result);
}
catch (IOException e) { ; }
if (amlConnection != null)
amlConnection.disconnect ();
return true;
}
I think you will have to look into the log files of the PLM application to find out why you do not get an HTTP response. There might be a number of possible reasons why the application is not working anymore after the upgrade.
I guess that it will be difficult to debug the problem based on the client code only. As the server seems to accept your HTTP, I would expect that this event and errors would be written to a log file somewhere. You might also want to try some graphical tool like SOAP UI to test the SOAP service.
I have android client and C++ server with working ssl (TLS) connection. But for every message I have to open new ssl session and so on.
Can I send multiple messages over one ssl socket? How?
I have tried reuse my one-message working code as below.
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(sslSocket.getOutputStream()));
w.write(request, 0, request.length());
w.flush(); // this works (server got data)
BufferedReader r = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
StringBuilder response = new StringBuilder();
String actRecieved = null;
while ((actRecieved = r.readLine()) != null) {
response.append(actRecieved);
}
Log.d("TEST", "one: " + response.toString()); // this works (server send data, I read it)
request = "some special request 2";
w.write(request, 0, request.length());
w.flush(); // this does not work, no data went to server, but no error occured
actRecieved = null;
response = new StringBuilder();
while ((actRecieved = r.readLine()) != null) {
response.append(actRecieved);
}
Log.d("TEST", "two: " + response.toString()); // this does not work as well, because server is not send any data
So, where is the problem? Can anyone tell me?
Update
I have just found out that 2 write requests will reach the server when I don't read from stream.
Is there any problem with using input and output stream mutliple-times from one socket?
Should I use two sockets - one for read and one for write?
Help anybody.
Ok, finally I found solution on my own.
The problem was in reading, because r.readLine() blocked until server closed connection, so after this nothing could be sent.
Now client is not waiting for server to close connection, but it checks if the message is complete.
Like this:
while ((actRecieved = r.readLine()) != null) {
response.append(actRecieved);
if(actRecieved.endsWith("SomeEndMark")
break;
}
Hope this will help to someone else.
I asked a similar question in another thread but I think I'm just having trouble getting the syntax right at this point. I basically want to open a socket in Java, send a HTTP request message to get the header fields of a specific web page. My program looks like this so far:
String server = "www.w3.org";
int port = 80;
String uri = "/Protocols/rfc2616/rfc2616-sec5.html#sec5.1"
Socket socket = new Socket(server, port);
PrintStream output = new PrintStream(socket.getOutputStream());
BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
output.println("HEAD " + uri + " HTTP/1.1");
//String response = "";
String line = "";
while((line = socketInput.readLine()) != null){
System.out.println(line);
}
socketInput.close();
socket.close();
It doesn't really work. Or it doesn't work for all websites. If someone could just tell me the immediate problems with what I'm doing, that would be great. Thank you!
Change
output.println("HEAD " + uri + " HTTP/1.1");
to
output.println("HEAD " + uri + " HTTP/1.1");
output.println("Host: " + server);
output.println();
You have to send the Host header because usually there are more than one virtual host on one IP address. If you use HTTP/1.0 it works without the Host header.
I would use some higher-level component, like HttpURLConnection (see here) or apache http components.
I am trying to read from a tcp stream a message sent from client.
Thing is after reading the last line, my readline function is not returning null and i am not able to debug why, as control point is lost.
In short, after last line read, readLine function should return null, but i am not getting any thing as such.
this is what my code looks like
StringBuffer sipBuffer = null;
String lineRead = null;
readIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
try {
sipBuffer = new StringBuffer();
while ((lineRead = readIn.readLine()) != null) {
sipBuffer.append(lineRead);
sipBuffer.append("\n");
}
} catch (Exception ex) {
sipConsole.addText("Error in message: \n");
sipConsole.addText(ex.getMessage());
return;
}
format of message is
String inviteReq = "INVITE sip:" + destIP + "#sip.umsy.edu SIP/2.0" + "\n"
+ "From: \"" + myName + "\" <sip:" + myIP + "#sip.umsy.edu>" + "\n"
+ "To: <sip:" + destIP + "#sip.umsy.edu>" + "\n"
+ "Allow: INVITE, ACK, BYE" + "\r\n";
Has the client closed the stream it is writing to? If it hasn't, your readLine() is blocking for more data from the client. Client-server protocols typically establish a mechanism (other than stream close) to indicate size. Whether it is a content-length or through a special token.
readLine() will return null when the stream is closed. Are you really sure the stream gets closed ?
It seems you're reading a SIP message in which case the other end probably won't close the connection until the call is complete- or atleast until it's either answered or terminated before it gets answered. You'll have to follow the SIP protocol, and handle messages on the stream according to the SIP spec.
Please check if you are flushing and closing the OutputStream on the client side to not have your InputStreamReader blocked and waiting forever on the server side?
Be sure to close the connection on the client side once the message is sent. Otherwise, the server side will block and wait for more data.
I suspect that the client did not close the socket after sending the message, so the server is blocked waiting for new lines. Is this the case?
Remember that readline() returns null only if the end of stream is reached.
If your protocol requires a constantly open connection between the client and the server, you will have to detect the end of message in a different way.