这几天在自学socket网络编程时突然要用到文件和文本同时传输到服务器,
但是在网上找了半天页找不到具体的结局办法,最后在不断琢磨之下终于解决了这个问题,
在传输数据时使用的是java中的objectinputstream
和 objectoutputstream
对象流,
这个流可以封装复杂的数据在网络中进行传输,
发送涉及到的类需要实现serializable
接口,是一个标志接口,用于序列化的,没有任何的方法需要实现。
废话不多说,直接上代码
第一种方案
student类,用于封装数据进行传输和解析
public class student implements serializable { private string username; private string sex; private byte[] file; private string filename; public string getusername() { return username; } public void setusername(string username) { this.username = username; } public string getsex() { return sex; } public void setsex(string sex) { this.sex = sex; } public byte[] getfile() { return file; } public void setfile(byte[] file) { this.file = file; } public string getfilename() { return filename; } public void setfilename(string filename) { this.filename = filename; } @override public string tostring() { return "student{" + "username='" + username + '\'' + ", sex='" + sex + '\'' + ", filename='" + filename + '\'' + '}'; } }
客户端
public class clientsocket { public static void main(string[] args) throws ioexception { socket socket = new socket("127.0.0.1",9999); // 获得socket输出字节流 outputstream os = socket.getoutputstream(); student student = new student(); student.setusername("765652244"); student.setsex("男"); // 获取文件地址 file file = new file("c:\\users\\网络杀手\\desktop\\image\\soft\\bg.png"); // 将文件名保存到student中 student.setfilename(file.getname()); // 获得文件字节输入流 fileinputstream fis = new fileinputstream(file); // 将文件字节流保存至字节输出缓冲流 bytearrayoutputstream bos = new bytearrayoutputstream(fis.available()); byte[] b = new byte[1024]; int len = -1; while((len = fis.read(b)) != -1) { bos.write(b, 0, len); } // 将得到的文件字节转换为字节数组 student.setfile(bos.tobytearray()); // 将socket输出流进行转换 objectoutputstream oos =new objectoutputstream(os); // 将对象输出流发送到服务器 oos.writeobject(student); fis.close(); bos.close(); oos.flush(); oos.close(); system.out.println("发送成功"); } }
服务器
public class serversocketdome { public static void main(string[] args) throws ioexception, classnotfoundexception { serversocket serversocket = new serversocket(9999); // 监听9999端口,等待客户端连接,如果没有连接,将会一直阻塞 socket accept = serversocket.accept(); // 获得数据输入流, inputstream is = accept.getinputstream(); // 对数据输入流进行转换 objectinputstream ois = new objectinputstream(is); // 将获得的数据转换为studen类 student o = (student)ois.readobject(); system.out.println("用户名:"+o.getusername()+"\n"+"性别:"+o.getsex()); system.out.println("文件名:"+o.getfilename()); // 将获得的文件保存至磁盘中 file file = new file("d:\\"+o.getfilename()); // 获得输出流,准备将内存中的数据写到磁盘 fileoutputstream fos = new fileoutputstream(file); // 将student类中或的文件字节写入磁盘 fos.write(o.getfile()); fos.close(); serversocket.close(); accept.close(); is.close(); ois.close(); system.out.println("保存成功,文件名是:"+o.getfilename()+"\n存在在:"+file+"目录下"); } }
结果
第二种方案
不需要封装类,也不需要实现serializable
接口
服务端
public class serversocketdome1 { public static void main(string[] args) { try { serversocket serversocket = new serversocket(9999); socket socket = serversocket.accept(); // 对象流 objectinputstream ois = new objectinputstream(socket.getinputstream()); // 读取文件名 string str = ois.readutf(); system.out.println("文件名:"+str); // 读取文件大小 long l = ois.readlong(); system.out.println("文件大小为:"+l); // 这是使用的是缓冲流,避免了文件大时内存溢出 bufferedoutputstream bos = new bufferedoutputstream(new fileoutputstream(new file("d:\\"+str))); byte[] buffer = new byte[1024*1024]; int len = -1 ; while ((len=ois.read(buffer))!=-1){ bos.write(buffer,0,len); } ois.close(); bos.close(); socket.close(); serversocket.close(); } catch (ioexception e) { e.printstacktrace(); } } }
客户端
public class client1 { public static void main(string[] args) { try { socket socket = new socket("127.0.0.1",9999); outputstream os = socket.getoutputstream(); objectoutputstream oos = new objectoutputstream(os); file file = new file("c:\\users\\网络杀手\\desktop\\image\\soft\\bg.png"); fileinputstream fis = new fileinputstream(file); bufferedinputstream bis = new bufferedinputstream(fis); // 写入文件名 oos.writeutf(file.getname()); // 获得文件大小 oos.writelong(file.length()); byte[] buffer = new byte[1024*1024]; int len =-1; while ((len=bis.read(buffer))!=-1){ oos.write(buffer,0,len); } oos.flush(); os.close(); oos.close(); fis.close(); bis.close(); socket.close(); } catch (ioexception e) { e.printstacktrace(); } } }
结果
两种方案中明显是方案二要简便些,但是各有个的优点:
方案一中发送的数据需要封装,解析时候方便(可以将bytearrayoutputstream换成bufferedinputstream
)如果是多个文件,对student类中的属性进行一下变更,就能够实现
第二种方案中需要使用gson数据封装之后发送和解析,对于负杂的数据时还是要进行封装之后才能发送,否则服务器不好解析。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论