I want to Transfer file with tcp client to server, but image file has been wrong.
My client code is
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream
import org.msgpack.core.MessageBufferPacker
import org.msgpack.core.MessagePack
import org.msgpack.core.MessageUnpacker
import java.io.*
import java.net.Socket
import java.util.*
fun main(args: Array<String>) {
fileClient("localhost",1988,"fruit.jpg")
}
class fileClient (host:String, port:Int, file:String){
var s : Socket ?= null
var out = ByteArrayOutputStream()
var msg : MessageBufferPacker = MessagePack.newDefaultBufferPacker()
init {
try {
s = Socket(host,port)
sendFile(file)
}catch (e:Exception){
e.printStackTrace()
}
}
@Throws(IOException::class)
fun sendFile(file: String) {
val dos = DataOutputStream(s!!.getOutputStream())
val buffer = ByteArray(4096)
val filebytes = File(file).readBytes()
var msgdata = ByteOutputStream()
msg.packString(file)
msg.packBinaryHeader(filebytes.size)
msg.writePayload(filebytes)
msg.close()
val data = msg.toByteArray()
val datasize = data.size
val ins = ByteArrayInputStream(data)
dos.writeInt(datasize)
while (ins.read(buffer) > 0) {
dos.write(buffer)
}
dos.close()
}
}
And my server code is
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream
import org.msgpack.core.MessagePack
import org.msgpack.core.MessageUnpacker
import java.awt.List
import java.io.*
import java.net.ServerSocket
import java.net.Socket
import java.text.SimpleDateFormat
import java.util.*
fun main(args: Array<String>) {
var fs = FileServer(1988)
fs.start()
}
class FileServer(port: Int) : Thread() {
private var ss: ServerSocket? = null
var fileRealName : String ?= null
init {
try {
ss = ServerSocket(port)
} catch (e: IOException) {
e.printStackTrace()
}
}
override fun run() {
while (true) {
try {
val clientSock = ss!!.accept()
saveFile(clientSock)
} catch (e: IOException) {
e.printStackTrace()
}
}
}
@Throws(IOException::class)
private fun saveFile(clientSock: Socket) {
var msgList = ArrayList<Any>()
val dis = DataInputStream(clientSock.inputStream)
val msgdata = ByteOutputStream()
val buffer = ByteArray(4096)
var read = 0
while (true) {
val datalen = dis.readInt() // data length
if(datalen!= null && datalen >0){
var finaldata = ByteArray(datalen)
var process = 0;
while (process <= datalen) {
read = dis.read(buffer)
if (read < 0) {
return
}
msgdata.write(buffer)
process += 4096
}
println(process.toString() + " "+ datalen.toString())
var allData = msgdata.toByteArray().slice(0..datalen).toByteArray()
unpackByte(allData)
}
}
msgdata.close()
dis.close()
}
private fun unpackByte(data:ByteArray){
var unpacker : MessageUnpacker = MessagePack.newDefaultUnpacker(data)
var fileName = unpacker.unpackString().toString()
var filesize = unpacker.unpackBinaryHeader()
var buffer = ByteArray(filesize)
unpacker.readPayload(buffer)
var fos = FileOutputStream(fileName)
fos.write(buffer)
fos.close()
unpacker.close()
}
}
And a file what I want to transfer is
but after transfer, image on server is like this.
How can I transfer this file correctly?
I didn't succeeded in reproducing your problem. However I think I've found the bug that may be causing corrupted file transfer.
In your server code there's an infinite loop that returns immediately out of method leaving the rest of method unreachable. This is the clean-up code that closes connections and streams. Quite possibly the OutputStream
was not properly closed and this is the cause of corrupted file write.
That's how the server code should look like:
val datalen = dis.readInt() // data length
if (datalen > 0) {
var finaldata = ByteArray(datalen)
var process = 0;
while (process <= datalen) {
read = dis.read(buffer)
if (read < 0) {
break
}
msgdata.write(buffer)
process += 4096
}
println(process.toString() + " " + datalen.toString())
val allData = msgdata.toByteArray().slice(0..datalen).toByteArray()
unpackByte(allData)
}
msgdata.close()
dis.close()
while
loop is unnecessary. Also you probably should just break
the loop, not return
from function.
P.S. Have you considered using IOUtils to handle all the IO read/writes? Half of your code could be replaced with just a few lines of code using this library.