Java Sockets - Files transfered simulatanously with other data over one connection
I have a multi-threaded server that handles client requests, and makes new threads for each one that is connected. This is working great and I am able to send "text" messages back and forth to the server without a problem. Like a chat system.
Now I have in mind a way to be able to send files across these client connections to the ser开发者_运维技巧ver, but every single example I see in java always has a hard-coded file name on server / client side - but I want to set my own for flexibility. And I would love if it were not only able to not only receive files but also receive "text" messages on the same port simulatanously.
I have an idea whereby the "text" message port I have at the moment, tells the server a file is going to be sent from a client, then the server opens up a "file transfer" port, just for file transfers. That way the "text" port could specify the name etc of the file. And the other port could send the files quite happily, without interruption.
Does anyone know a better way to do this though? I don't really want to use two ports, it seems a bit messy. I would prefer to make a separate thread on the server side to deal with the file transfer and also deal with "text" message at the same time, if this is even possible?
Thanks in advance, I hope I have been clear enough :)
Sure, it's easy. You just have to specify the message type first. Either with a byte or with a line of text.
The easiest way would be with a single byte like this:
//to send
Socket s = ...
OutputStream os = s.getOutputStream();
if(messageIsText()){
os.write(0);
//send text
else{
os.write(1);
//send file
}
then in your server you could do this:
Socket s = serverSocket.accept();
InputStream in = s.getInputStream();
int firstbyte = in.read();
if(firstbyte = 0){
//read text
}
else{
//read file
}
Now, that's not very flexable, but there are lot of things you can do. I would actually recommend you read RFC 2616, that's the specification for HTTP. You don't need to read the whole thing, and just the enough to write a simple web server. It's actually really easy (HTTP is a really simple protocol at the core, although it has a lot of advanced features now)
If you really want to learn network programming, try writing an HTTP server. That might sound daunting, but don't worry, it's actually not that hard at all.
Sounds like you're re-inventing FTP. You might want to look at FTP servers implemented in Java. WebDAV as well.
Chuck the file in pieces and send them along the "normal" line.
Something link:
- text message
- start file (id <-- id number invented by the client, filename)
- file piece (id, with some bytes in a byte[])
- end file (id)
the server receives the start file and start a new structure saving: * client id * invented id (and name why not! :)
next with each file piece add that bytes (maybe writing to disk or something)
The end file meesage would say: ok, flush and close!
The server can save the files in a map, mapping from a Key object (clientid+fileid) to the temp structure.
Waht you describe is pretty much how FTP works. And yes, it is messy, especially the part where the server opens a port, because that simply does not work in this age of firewalls and NAT. Thus, FTP had to add a "passive mode" where the client opens the additional port.
But there's really no reason to have separate ports. Why not simply have one kind of text message that announces "here comes a file", and send the file right afterwards on the same port?
Well, you have two options: out-of-band transfer (as FTP, yeah, the guys and lads above already had said that), or you may do some interleaved streaming. For example, on the client you issue a type/size header into the stream and then dump your file segment or text message (of the corresponding byte length). On the server you may read/write file segments via one per-connection thread, while handling text messages in some central consumer thread (with one async producer per connection thread).
For that cool interleaving you may try either google protobuf library - they have nice primitives to read/write small chunks of data to the stream, or a plain/old Object(In|Out)putStream.
精彩评论