I'm recently learning how to create sockets to connect to a webserver. I've managed to write a little something in Java:
BufferedReader inUser = new BufferedReader(new
InputStreamReader(System.in));
Socket clientSocket = new Socket("www.google.com", 80); // url expected
DataOutputStream outServer = new DataOutputStream
(clientSocket.getOutputStream());
BufferedReader inServer = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
String sentence = inUser.readLine();
outServer.writeBytes(sentence + '\n');
String modifiedSentence = inServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
inUser.close();
outServer.close();
inServer.close();
clientSocket.close();
I'm also using a socketTest program (from http://sockettest.sourceforge.net/) to test my client. The connection seems fine and I can use the sockettest to receive and send back messages (by hosting a local server). When I try to send a string to a webserver (in my java code it's named 'sentence'), it returns bad requests for random input like 'sd' or 'a', as expected. However, when I type the query I wished to receive feedback on, I don't receive anything. To be sure, this is what I put in (stored in 'sentence'):
GET index.html http/1.0
Either I should get the file if it exists or an exception if something went wrong, right? I don't receive anything though. Stranger yet, I've noticed that the first time I give input, I just have to make sure I have 3 separate random strings (separated by space) to have it accepted as valid input. And any random input I enter afterwards, like 'sd' will also be accepted.
Another observation I made is that the program keeps running. Normally I should read a single line then the program stops. This means it wasn't able to read anything.
I'm using port 80 for all the pages I've tried. Here's a small list of websites I've tried to perform a query on:
- www.google.com
- en.wikipedia.org
- www.cracked.com
I've tried a few others setup for the sole purpose of tutorials. Why don't I receive anything? When I tried it with telnet some seemed to work (though www.google.com always returned a xxx error found).
Try writing an additional "\r\n" before flushing the output stream:
BufferedReader inUser = new BufferedReader(new InputStreamReader(System.in));
URL url = new URL("http://www.google.com");
Socket clientSocket = new Socket(url.getHost(), 80); // url expected
OutputStream output = clientSocket.getOutputStream();
PrintWriter pw = new PrintWriter(output,false);
pw.print("GET index.html HTTP/1.0\r\n");
pw.print("\r\n");
pw.flush();
BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String modifiedSentence = input.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
Related
I have a Java TCP server, and an android TCP client. I'm trying to send data from client to server. Sending the data seems to be working fine, but the data that is sent, seems corrupted.
Socket connectionSocket = socket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader( connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println(clientSentence);
System.out.println(clientSentence.split(":")[0]);
if(clientSentence.split(":")[0].equals("packet"))
{
When the server receives the data, the prints show something like this in the console:
packet:user:pass
packet
Which is as expected. But still my if isn't returning true. As if the "packet" string got from socket, is different from the one I type with keyboard in my source. I can't even copy the text from console. When I copy with mouse and paste it somewhere, it only copies the first character.
I use the same structures on client side and send the packet with [DataOutputStream].writeChars(message)
I don't know if it's a different coding of characters that cause this, or something else. Also it's worth noting that when i capture the text with wireshark, the string is something like ".p.a.c.k.e.t"
Thanks.
EDIT: As asked, client side code is something like this:
Socket clientSocket = new socket("127.0.0.1", 1234);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream());
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
String message = "packet:" + username + ":" + password + "\n";
outToServer.writeChars(message);
It's on an android device.
I'm trying to send a string from my c client to a Java server, after which the server sends a text file to the client.
This is the part of client code that sends the string.
int n = write(sock_fd,"Ready",5);
if (n < 0)
printf("ERROR writing to socket\n");
recv_file(sock_fd, filename);
And this is the server part of java code:
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
System.out.println("Message received from client is " + message);
String FILENAME = "data.txt";
sendFile(socket, "data.txt");
Now I have verified that if I remove the part in the server code where it tries to read the string from c client, the rest of the code works fine and the file is transmitted. But if do not comment the string receiving code, both the server and client keep waiting.
I will be grateful if somebody solves this issue for me.
P.S. I know this question has been asked before but that didn't help me, so I started a new thread.
br.readLine() wants to read a line. The client never sends a newline, so the server is waiting for a newline... forever!
Add a newline to the command sent by the client:
int n = write(sock_fd,"Ready\n", 6);
I have been playing around with UPnP, to get an understanding of how it all works, before I try working with any of the APIs that are out there, or doing anything more substantial. I have been reading through the UPnP documentation, and have used that information to format the messages that I am sending. I am just working from the command line right now, and have gotten discovery messages to work without issue. Now, I'm trying to return content from a ContentDirectory Browse() request (I have also tried TransportAV GetMediaInfo() because it takes only one argument). However, no matter what I try, I am getting a Null response from the MediaServer.
public class SOAPSocket2 {
public static void main(String[] args) {
try {
String xmldata = "<?xml version=\"1.0\"?>" +
"<s:Envelope " +
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/ \"" +
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
"<s:Body>" +
"<u:GetMediaInfo xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">" +
"<InstanceID>0</InstanceID>" +
"</u:GetMediaInfo>" +
"</s:Body>" +
"</s:Envelope>";
//Create socket
String hostname = args[0];
int port = Integer.parseInt(args[1]);
Socket sock = new Socket(hostname, port);
//Send header
String path = args[2];
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),"UTF-8"));
// You can use "UTF8" for compatibility with the Microsoft virtual machine.
wr.write("POST " + path + " HTTP/1.1\r\n");
wr.write("HOST: " + hostname + ":" + port +"\r\n");
wr.write("CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n");
wr.write("SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#GetMediaInfo\"");
wr.write("\r\n");
//Send data
wr.write(xmldata);
wr.flush();
// Response
BufferedReader rd = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line;
line = rd.readLine();
System.out.println(line);
while((line = rd.readLine()) != null)
System.out.println(line);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I know this isn't the most proper code, but I borrowed it from here: http://users.skynet.be/pascalbotte/rcx-ws-doc/xmlpost.htm. I figured that if I could actually get some sort of data in a response, then I could work on building it properly. I have modified it so that I pass the IP address and Port of the Media Server from the command line, as well as the path to the Control URL. However, I am getting nothing but 'null' from the Media Server. Any thoughts on what I'm doing incorrectly? Thanks
I am getting a Null response from the MediaServer
Is that a response from MediaServer? I would imagine it's just BufferedReader telling you there's nothing to return.
You have two things here you can debug (sending and receiving) but the same tools should help with both. Use wireshark or another network traffic capture tool to see the actual data that goes through the network. Wireshark will tell you if the response is sent (but you are failing to receive it properly) or if the reply never comes (implying your message is incorrect). It will also show your message as it is on the wire, making it easier to notice mistakes.
Doing the above (and pasting the messages here if you can't figure it out) is the best way to continue debugging, but I can see some problems in the code already:
SOAPACTION-line is missing "\r\n" in the end
There is no CONTENT-LENGTH header (this is required in normal cases)
These aren't even UPnP problems really, the message just isn't proper HTTP. Still, the UPnP Device Architecture document will help with problems like this.
I am trying to have my client connect to my server, and depending on the command send some string back to the client. Currently the app connects and can send strings to the server very nicely. However when I send the command which instructs the server to send something back it hangs. I found that the problem occurs when the client attempts to read the line send from the server.
Server
PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
out.println("GETDATA" + "\n");
out.flush();
out.close();
Client
BufferedReader fromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
incomingLine = fromServer.readLine();
Log.d("HERE", "NOT " + incomingLine);
fromServer.close();
Thanks!
I made effectively this same mistake when I was first doing sockets as well.
Don't use PrintWriter with BufferedReader. They're incompatible. By comments, PrintWriter actually hides critical exceptions, so they shouldn't be used in networking. Instead, use a DataInputStream and DataOutputStream for communications.
client = new Socket(hostname, port);
inStr = new DataInputStream(client.getInputStream());
outStr = new DataOutputStream(client.getOutputStream());
Then, send and receive using writeUTF and readUTF, like so:
public void send(String data) throws IOException {
outStr.writeUTF(data); outStr.flush();
}
public String recv() throws IOException {return inStr.readUTF();}
The reason has to do with the UTF encoding; a BufferedReader expects a certain string encoding, which PrintWriter does not give. Thus, the read/write hangs.
The method readLine() expects an end of line character "\n" maybe that's your problem
I'm writing a proxy and have the following code:
Socket conUser;
Socket conDest;
try{
ServerSocket ss = new ServerSocket(Integer.parseInt(p.getProperty("proxy.port")));
while(true){
//Connect to user
conUser = ss.accept();
BufferedReader inputFromUser = new BufferedReader(new InputStreamReader(conUser.getInputStream()));
BufferedWriter outputToUser = new BufferedWriter(new OutputStreamWriter(conUser.getOutputStream(), "UTF8"));
//Get user request
StringBuffer req = new StringBuffer();
getUserRequest(inputFromUser, req);
System.out.println("User requested the following:");
System.out.println(req);
//Connect to server
InetAddress a = InetAddress.getByName(determineHost(req));
conDest = new Socket(a,80);
//Send request to server
BufferedWriter outputToServer = new BufferedWriter(new OutputStreamWriter(conDest.getOutputStream(), "UTF8"));
InputStreamReader inputFromServer = new InputStreamReader(conDest.getInputStream(), "UTF8");
outputToServer.write(req.toString());
outputToServer.flush();
System.out.println("==============================");
System.out.println("Server replied with the following:");
//Read reply from the server
//=========================================
int chars;
while ((chars = inputFromServer.read()) != -1) {
System.out.print((char)chars);
outputToUser.write(chars);
outputToUser.flush();
//serverReply.append(chars);
}
//Relay reply to user
//outputToUser.write(serverReply.toString());
//System.out.println(serverReply);
//outputToUser.flush();
conUser.close();
conDest.close();
}
}
catch (Exception e) {
System.err.println(e);
}
What happens is: I make a connection and it succeeds. I also send the request, and that succeeds too. I also get a reply, and am able to load the entire page's HTML, except that the read doesn't seem to terminate when it reaches the end of the content.
Specifically, I was attempting to load Google's homepage and the chunked transfer reached 0 (that is- end of chanked transfer), and thus there should've been no more input to read, but this did not cause the loop to stop reading. What's also strange to me is that pretty much all code examples of proxies do use this loop, and assuming they work, I don't see much differences between their code and mine.
How do I make the loop terminate correctly?
EDIT: for the record, yes- I know that the TCP connection should be kept open to handle further connections. This is not relevant to the problem I'm having. I need to get this loop to terminate per response.
In general the connection is not closed at the end of each response. Creating TCP connections is relatively time-consuming so the connection is left open, ready for you to send your next request.
Here are a couple of explanatory links:
http://en.wikipedia.org/wiki/HTTP_persistent_connection
http://en.wikipedia.org/wiki/HTTP_pipelining
If you want to terminate connection correctly after receiving HTTP response, your simple loop is not enough. You have to determine the end of message as described in section 4.4 Message Length of RFC 2616 and then close the connection.
However, it would be better to use existing libraries, such as built-in URLConnection.