Supposing I have a servlet that reads and writes a file to a socket and I want to establish a connection between the servlet and the socket, how could this be done?
Well, for a socket, i read somewhere that one just has to do this:
URL url = new URL("http://example.com/getFile");
URLConnection con = url.openConnection();
con.setDoOutput(true);
How could I do the same for a servlet?
I wanted to do this since I will be sending and receiving files between the servlet and the scoket. Also, how would both of them know when the other has sent a file and should read it?
I have searched for this but can't find any site that explains it.
I am unsure what do you mean by 'Socket'. If the socket is a standard protocol (http/https/ftp) then you can use the above piece of code in the Servlet just as you would use in a stand alone program.
If your socket does NOT prescribe to any standard then you might want to open a direct connection using the below piece of code:
Socket socket = new Socket(server,port);
//Get an input stream from the socket
BufferedReader inputStream =
new BufferedReader(new InputStreamReader(
socket.getInputStream()));
//Get an output stream to the socket. Note
// that this stream will autoflush.
PrintWriter outputStream =
new PrintWriter(new OutputStreamWriter(
socket.getOutputStream()),true);
outputStream.println("send_ data");
System.out.println(inputStream.readLine());
socket.close();
Regarding the file sending piece of code, if the primary task involved is file transfer you can use FTP protocol to send files between the servlet and socket.
you can have a file watcher on the socket end to know when a file is transferred. Refer filewatcher and ftp for more information.
You confuse servlets and sockets it looks like. Here is the difference:
Sockets are used for a low-level communication between two points in network. By low-level I mean that you basically send whatever binary data you want over socket and receive some data back. In order to establish a connection there should be a ServerSocket waiting for connections and client socket which establishes connection with server socket.
Servlet is J2EE abstraction. Servets are used in web application containers and those work on top of some protocol (in most cases HTTP). Servlets don't work with sockets, although web server uses sockets internally. Servlets work with Request and Response objects. Your servlet is responsible for processing user request and forming a response.
Related
I have Java Client-Server application I built using standard java.io (Socket and ServerSocket). In both server and client, I use DataInputStream to read the message using readUTF and DataOutputStream to write the message using writeUTF. I use thread-per-connection architecture for this application.
I have an additional feature that I need to add now, which is allowing a client to have a persistent connection open to the server and always listening to what server will write. I found out, with my current thread-per-connection architecture, my application won't scale because it holds the thread when the client opens the persistent connection.
I did some research and think to refactor my server to use java.nio (SocketChannel and ServerSocketChannel). I try to make it compatible with the client (so I don't need to change the client). This is when the problem occurs because I need to change from readUTF method to using ByteBuffer class to read the message, now I got a weird character in my message.
This is my message that works before using readUTF (Server) that come from writeUTF (Client)
{"command":"PUBLISH","resource":{"name":"","description":"","tags":[]}
When I sent the same message to my new server, I got this in my read method
�{"command":"PUBLISH","resource":{"name":"","description":"","tags":[]}
My read method is:
else if (clientKey.isReadable()) {
SocketChannel clientSocket = (SocketChannel) clientKey.channel();
ByteBuffer buffer = ByteBuffer.allocate(4096);
clientSocket.read(buffer);
String message = new String(buffer.array());
Logger.debug(message);
clientSocket.register(selector, SelectionKey.OP_WRITE);
}
This is how I write the message from client:
try (Socket echoSocket = new Socket(hostName, portNumber);
DataOutputStream streamOut = new DataOutputStream(echoSocket.getOutputStream());) {
streamOut.writeUTF(message.toJson());
}
toJson() is just a method to convert java object to JSON string and I use Jackson library to do that.
I have tried to remove it using regex and Normalizer library but it won't work.
Is there anyone experience the same things and solve it?
I'm writing a ServerSocket in java. I want to send some special content to client connecting to me through telnet. I want to send other content if he/she connects through Browser and etc. Is there any way to find out that user is connecting to me with telnet?
My code :
public void handleConnection(Socket socket) throws IOException {
String author = "Ehsan Akbari";
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
if(checkoutClientType(socket)=="telnet")
out.println("You are connecting through telnet :\)");
else
out.println("You are not connecting through telnet :|");
}
What should be the definition of checkoutClientType(Socket s);?
You cannot tell what program is on the other side of a socket by examining the socket itself. There is no test or operation you can perform on the socket that will distinguish the client program.
The only hope is to examine the data being transmitted to see if it matches an expected pattern, but for that you have to have some data transmitted. It might be possible to tell if the remote is telnet if you were to send a Telnet Protocol command such as AYT (Are You There), but that would probably not sit well with a different client such as a browser.
If you were able to proxy the data between the client and a handling process or thread and examine it you might be able to eventually determine if it was Telnet, but probably not, and probably not immediately.
I need a java program to download a series of file from a web server and I need to be able to close and then reopen the tcp/ip connection between each file download.
Not sure how to do this.
Here is a low-level way of retrieving any information from not only socket 80 (http) but generically to retrieve mail, do a 'telnet' etc:
socket = new Socket();
socket.connect(new InetSocketAddress(host, port));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
now to do a call to retrieve a page, send the get command, set the content-type, and send two '\n'.
There is a higher-level solution:
Send HTTP GET request with header
You can create a Socket for the IP and port you want to send it to, then read the file into a byte array using a FileInputStream and send that byte array through a DataOutPutStream, then when done just flush the dataOutPutStream and close the Socket and call the function again sending the next file.
use the logic:
Please post something that you have tried.
do{
connection.open;
while(!eof){
fetchfiles();
}
connection.close;
}while(no of files yet to download);
I want to send an InputStream containing XML from the client to a server. Said server manipulates the XML stream using Streaming API for XML (StAX) and sends it back to the client.
I mange to send the XML to the server, the client receives the answer, but doesn't exit because the server never finishes reading the InputStream form the client.
But when the server is just dumping the input to System.out instead of sending something, reading finishes...
edit I forgot to mention that IOUtils.copy() is running in two separate threads on the client.
Here some code to reproduce this, I've replaced the StAX part with IOUtils.copy() on the server.
Server
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
Client
Socket socket = new Socket(host, port);
FileInputStream fin = new FileInputStream(file);
OutputStream out = socket.getOutputStream();
IOUtils.copy(fin, out)
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
You must flush and close InputStream and OutputStream.
like this:
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
//add
out.flush();
in.close();
out.close;
You are probably creating a deadlock.
Client - sends data to the server.
Server - loops data back to the client.
Client - reads data (that the server looped back)
So, while the client is sending data to the server, the server is sending it back to the client.
The client isn't reading that data, it's busy sending.
At some point the TCP buffers fill up, and the server blocks on sending more data to the client. This means the server is blocked on sending data, so eventually the TCP buffers on the receiving side of the server fills up as well, and the client blocks on sending data. Since the client is now blocked on sending, it'll never get to the part where it reads the data that is looped back, so the server will never un-block.
If you're sending a small document, you might not experience this, as all the data fits in the buffers, but once you fill up the buffers, the system will deadlock.
You have to multiplex the sending/receiving. e.g. you could start up a thread on the client that does
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
That way receiving can be done in parallel with the client sending data
Or you could use 2 threads on the server side. One for receiving the data, posting data to be sent back to another thread doing the sending (you'll have to build up an internal queue in this case between the threads).
As far as I remember IOUtils.copy() does not flush and does not close the stream. It seems that you do not call neither flush nor close too. Try it. I believe that this is your problem.
I am working on a chat implementation with Java sockets. I have focused on few functionalities, like authentication, one person chat and a group chat. I was thinking about adding file transfer functionality, and I wonder what's the good practice about this. Should I have separate socket on the server with different port listening just for file transfers? Right now input and output streams that I get from server socket are binded to Scanner and PrintWriter objects respectively, so I find it hard to use that for file transfer.
Any patterns you guys could recommend or give me good recommendations are very appreciated.
Thanks,
ZeKoU
Well, FTP creates a new socket for each file transfer. Note that the connection can be established on the same port as the one used for chat, but with a different initialization dialog.
If you can use a native lib do that, it will be faster. Failing that unless there is a really good reason use a library which will have had all the kinks worked out.
If you really need to send a file in pure Java. Here's one way based on an old project of mine. Note however that there is some serialisation overhead however much of this could be removed via use of the NIO equivalents as discussed here or you could go slightly further and use Zero Copy which lets you tell the OS to copy a file direct to a socket without any intermediary copies. This only works with files though not other data.
You should do this in a separate thread so that the chat still works while the file is transferring. Create a socket and give it some standard port (you can give it port 0 which just chooses the next available port but then you will need to send that information to the other recipient so just using a standard port is easier). Then split your file into blocks and transmit it using the socket:
//Send file (Server)
//Put this in a thread
Socket socket = new Socket(destinationIP, destinationPort);
ObjectOutputStream sender = new ObjectOutputStream(socket.getOutputStream());
sender.writeObject(dataToSend);
//Receive File (Client)
//Kick off a new thread to receive the file to preserve the liveness of the program
ServerSocket serverSocket = new ServerSocket(ListenPort);
socket = new Socket();
while (true) {
new Thread(new TCPReceiver(socket)).start();
}
//Receive file thread TCPReceiver(Socket socket)
//Get the stream where the object is to be sent
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
/* Where type is the type of data you send... String or anything really...
read part of the file into something and send it then at this end use the same data
type to recieve it and it will magically pull the entire object across.
*/
while(fileIsIncomplete){
type recievedData = (type) objectInputStream.readObject();
//Reconstruct file
}
Hope that is enough for you to get a quick file sender up and running :)
Edit: Removed nonsense statement. Added native point and zero copy mention.