我也不知道为毛我插代码会自动置顶,简直不能忍!!!
最近开始了艰苦卓绝暗无天日搞不死人不罢休的集训,也是希望经过一个暑假的努力可以进一步朝大神大牛大学霸的目标前进,从今天开始也要保持三天一篇技术博客的效率开始加油啦
话不多说
从最基础的开始
自定义协议来实现JAVA的消息文件传输(其实只要是基于字节,什么都能传)。
首先来说协议,嗯,听起来高大上?TCP/IP协议?HTTP协议?OSI协议?镜像加速P2P?哈哈哈哈,当一个问题你也不会的时候,就丢出一堆更高端的东西,显得高大上嘛
其实这里的协议说白了就是一套规则,至于后面的由于太高端我慢慢看完书慢慢写。。。
消息传输规则
第一个发送 消息类型 int型 1表示消息 2表示文件
发送消息时,先发送消息长度(int),在发送消息内容字节数组(byte[])
发送文件时,先发送文件名长度(int)文件内容长度(int)文件名字节数组(byte[])文件字节数组(byte[])
以上其实就是我们所谓的高大上的协议OTZ,
这里要说明一下,我们发送消息或者文件时是基于字节的,就是说我们的数据最小单位都是一个一个的byte,这样的好处是完全不用理会什么编码或者文件类型什么的,我们传输的都是基本的数据,只要按规则即协议传输,就不会出错
相反,如果按字符传输,就是说是一个字符一个字符地传输的话,会有很多坏处,比如
1.没有任何安全性可言,所有消息文件内容都会被解析出来过一遍。
2.(对于不同的编码模式,GBK和UTF-8会有完全不同的结果,)总之就是一堆乱码烦死你。
具体实现过程呢
服务器类 新建一个ServerSocket,并获取连接的Socket的输入流,然后通过IO向外输出消息或者文件
客户机类 根据主机的地址和端口新建一个Socket,然后通过DataOutputStream向主机输出消息流或者文件流
服务器代码
package cn.SSheng.Server; import java.io.DataInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /** * 简单服务器类 * @author SSheng */ public class ServerManager { //主函数 实例化对象调用方法 public static void main(String[] argsp){ new ServerManager().setupServer(8080); } //根据参数建立相应端口号的服务器 public void setupServer(int port){ while(true){ try { //新建一个ServerSocket ServerSocket server = new ServerSocket(port); System.out.println("建立服务成功"); //等待客户机连入,程序在连入前进入阻塞状态 Socket client = server.accept(); System.out.println("连接成功"); //得到客户机的输入流 InputStream input = client.getInputStream(); //为了方便数据处理,建立DataInputStream DataInputStream datainput = new DataInputStream(input); //调用处理消息方法 = =。 方法名过于脑残请无视 Communicate(datainput); } catch (Exception e) { e.printStackTrace(); } } } /** * 处理消息输入的方法 * @param datainput 客户机的数据输入流 * * 所有的异常什么的全部丢出去不管啦好麻烦 * @throws IOException * @throws InterruptedException */ public void Communicate(DataInputStream datainput) throws IOException, InterruptedException{ //根据自己定的协议,第一个先读消息类型 int type = datainput.readInt(); System.out.println(type); //类型1 消息 if(type == 1){ System.out.println("消息输入"); //读入消息字节长度 int length = datainput.readInt(); //新建一个等于消息长度的字节数组 byte[] msg = new byte[length]; //读入消息内容 //datainput.read(msg); datainput.readFully(msg); //输出消息内容 System.out.println(new String(msg)); } //类型2 文件 else if(type == 2){ //读取文件名的长度, int fileNameLength = datainput.readInt(); //读取文件内容长度 int datalength = datainput.readInt(); //根据文件名长度建立文件名数组,并读入相应字节的内容 byte[] fileName = new byte[fileNameLength]; datainput.readFully(fileName); //根据文件内容长度建立文件内容数组,并读入相应字节的内容 byte[] file = new byte[datalength]; datainput.readFully(file); //新建一个文件输出流向磁盘写文件 FileOutputStream f = new FileOutputStream("F:\\"+new String(fileName)); //把所有文件字节内容写出 f.write(file); //刷新此输出流并强制写出所有缓冲的输出字节 f.flush(); System.out.println("文件输出成功"); //关闭文件输出流 f.close(); } } }
客户机代码
package cn.SSheng.Client; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; /** * 简单客户机的实现 * @author SSheng * */ public class Client { //数据输出流对象 DataOutputStream dataoutput; //主函数 新建客户机对象并调用连接方法,连接方法里调用传输方法 public static void main(String[] args){ new Client().connect("127.0.0.1",8080); } /** * 连接服务器的方法 * @param ip 服务器IP地址 * @param port 服务所在服务器端口号 */ public void connect(String ip,int port){ try{ //新建一个Socket,连接到服务器的IP 和端口 Socket client = new Socket(ip,port); //获取客户机Socket对象的输出流对象 OutputStream output = client.getOutputStream(); //为方便数据输出,调用JAVA库根据输出流对象新建一个数据输出流对象 dataoutput = new DataOutputStream(output); //向客户机发送的两个方法 sendMsg("这是个坑",dataoutput); writeFile("D:\\Cool Edit Pro\\cep2unin.exe",dataoutput); //关闭客户机 client.close(); }catch(Exception e){ e.printStackTrace(); } } /** * 发送消息的方法 * @param msg 要发送的消息 * @param output 数据输出流对象 * @throws Exception 异常什么的你懂的 丢出去就好 */ public void sendMsg(String msg,DataOutputStream output) throws Exception{ //根据协议 int type = 1; byte[] message = msg.getBytes(); int msgLength = message.length; //发送消息类型,即1 output.writeInt(type); //发送消息字节长度 output.writeInt(msgLength); //发送消息内容 output.write(message); } /** * 传输文件的方法 * @param path 文件路径,绝对路径 * @param output 数据输出流 * @throws Exception 你懂的 */ public void writeFile(String path,DataOutputStream output) throws Exception{ //消息类型 int type = 2; //根据路径建立文件对象 File f = new File(path); //文件对象建立文件输入流好把文件读入进内存 FileInputStream finput = new FileInputStream(f); //调用available方法,会返回文件流指针所指位置到文件结尾的字节个数,即文件字节长度 int fileLength = finput.available(); //调用getName方法,会返回绝对路径最后面的名字,也就是文件的名字(如:warcraft.exe) byte[] fileName = f.getName().getBytes(); //文件名字的字节个数 int fileNameLength = fileName.length; //根据文件长度建立文件内容的byte数组 byte[] data = new byte[fileLength]; //从文件输入流中把文件读入 finput.read(data); //分别按协议的顺序 把消息类型(2,文件名长度,文件内容长度,文件名,文件内容输出 output.writeInt(type); output.writeInt(fileNameLength); output.writeInt(fileLength); output.write(fileName); output.write(data); //刷新此输出流并强制写出所有缓冲的输出字节 output.flush(); //关闭文件输入流 finput.close(); } }
最后说几个我犯过的错误吧
1.如果用输入输出流,即InputStream,OutputStream你会发现对象相应的读写方法都只有基于byte的,而如果你想读一个int,即四个字节,那么恭喜请去自己写一个位运算的方法进行转换,但是!!!JAVA怎么会让这张事情发生呢,所以一定要把输入输出流封装到数据输入输出流中,即DataInputStream DataOutputStream,然后你就会发现相应对象就有了温柔又贴心的int,byte,long,short等等等等的方法
2.得到的输入流会有一个read()方法和一个readFully()方法。readFully()方法会等数组所有数据都读取完毕后才会返回。
以下摘自某大神博客:http://xuyi1994.iteye.com/blog/2091742网路通信中,当发送大的数据量时,有这样一种可能:一部分数据已发送到对方,有一部分数据还在本地的网卡缓存中,如果调用read()方法,可能会提前返回而没有读到足够的数据,在传大块数据(如一次传送一个较大文件时)可能出错,而readfully()方法会一直等待,读取到数组长度的所有数据,才会返回。
3.在新建文件输出流时注意!
FileOutputStream f = new FileOutputStream("F:\\"+new String(fileName));这行代码,fileName还记得么,我们传输时是以字节数组传输的,如果你直接"F:\\"+fileName,那么恭喜,fileName会返回数组首地址,你得到的文件名就是一堆数据地址代码,所以要调用String的构造函数传入字节数组来构造字符串,然后创建文件
哦对了 至今还有一个问题没有弄懂, 我们在做通信时当Socket连接到ServerSocket后开始写数据,当我把所有数据都写进网络以后,需要保证Socket保持连接状态知道ServerSocket接收完数据呢?还是只要传输进网络然后就可以关闭Socket了? 如果有看到的大神求指教 么么哒。
/**
求知对我们而言最根本的,也许不是为了让我们变得更加高级,对人生报更多奢望——而是为了让我们更自由。只不过要想真正在知识里看到自由,需要恒久的努力与谦卑,以及不管懂了多少依然充满了对这个世界的好奇心。
我早有觉悟。
*/
相关推荐
在这个主题下,我们将深入探讨Socket通信的基本概念、工作原理以及如何应用于文件传输。 首先,Socket可以看作是网络上的端点,它允许应用程序通过网络发送和接收数据。在TCP/IP协议栈中,Socket分为两种类型:基于...
以下是对Socket通信文件传输的详细解释: 1. **Socket基本概念**: Socket,也称为“套接字”,是网络通信中的一个抽象概念,它代表了两台机器之间的一个连接端点。在TCP/IP模型中,Socket接口提供了应用层与传输...
本文件传输系统采用TCP协议进行通信,实现了windows与linux通信,打破了只能在windows下传输文件的弊端,本程序的编写对通信编程新手有很大的帮助作用,本系统目前只支持windows向linux发送多种类型文件,大文件传输...
网络通信和文件传输简单示例程序。使用TCP进行文件传输,使用UDP进行网络文本通信。同时使用多线程监听消息。
《Qt技术深度解析:构建多线程局域网通信及文件传输软件》 在现代软件开发中,局域网通信和文件传输是不可或缺的一部分。本文将深入探讨如何使用Qt库,结合VS2010环境,实现基于TCP和UDP协议的多线程局域网通信软件...
本篇将详细介绍C#中基于UDP的通信及文件传输的相关知识点。 首先,UDP是一种无连接的、不可靠的传输协议,它不保证数据包的顺序、完整性和可靠性,但具有较低的延迟和较高的传输效率。在C#中,我们通常使用System...
实现串口通信文件传输的第一步是建立连接。这通常涉及配置串口参数,如波特率、数据位等,并打开串口。在编程中,我们可以使用各种库来完成这个任务,如在Python中的pySerial库,C++的libserialport库等。 接着,...
在IT领域,网络通信是核心部分之一,尤其是局域网内的多用户通信和文件传输。本文将深入探讨基于TCP协议的局域网多用户通信和文件传送程序,结合"飞鸽传书"这一实例,来解析相关技术要点。 首先,TCP(Transmission...
2. **断点续传**:如果文件传输过程中出现中断,工具应能保存已传输的部分,并在恢复时从断点处继续,减少因网络不稳定导致的重传。 3. **数据压缩**:在传输前对文件进行压缩,可以减少在网络中传输的数据量,...
socket通信 QQ聊天 文件传输 socket通信 QQ聊天 文件传输 socket通信 QQ聊天 文件传输
总的来说,要改进"C# UDP通信+文件传输"的应用,开发者需要在接收到文件数据后提供一个用户界面,让用户选择保存文件的路径,同时考虑在网络通信中添加额外的错误恢复策略,以提高文件传输的可靠性。这是一个涉及到...
在这个"QT学习之文件传输和断点续传"的主题中,我们将深入探讨如何在QT环境中实现基于TCP的文件传输功能,并且特别关注断点续传技术。 首先,让我们了解TCP(Transmission Control Protocol)协议。TCP是一种面向...
在C#编程语言中,利用Socket API进行TCP通信可以构建高效、稳定的文件传输系统,特别是在处理大文件时,断点续传功能则显得尤为必要。下面,我们将深入探讨如何使用C#的Socket实现TCP大文件传输并支持断点续传。 ...
总结来说,C#的TCP通信涉及客户端和服务端的建立连接、数据传输以及文件传输等核心步骤。开发者需要理解TCP协议的工作原理,并熟练运用C#提供的网络编程API,才能实现高效、稳定的网络通信系统。在实际项目中,还应...
实现串口通信文件传输功能,采用API方式,实现串口通信文件传输功能
《使用Visual C++实现大文件传输与断点续传及即时通信系统》 在现代计算机技术中,文件传输是一项基础且重要的功能。特别是在局域网或互联网环境中,用户经常需要在不同的设备之间交换大量数据。Visual C++作为...
服务器在发送文件时,可以设定合适的缓冲区大小,每次发送缓冲区中的数据,直到文件传输完毕。 7. 错误处理与调试: 网络编程中,错误处理至关重要,因为网络环境不稳定,可能出现各种异常情况。开发者需要对可能...
总结来说,Java中的Socket通信为客户端和服务器提供了双向通信的接口,可以用于文件传输。客户端通过建立Socket连接,读取文件内容并写入Socket的输出流,而服务器端则接收这些数据并保存到本地。这个过程涉及到了...
在本文中,我们将深入探讨如何使用VC++通过MFC(Microsoft Foundation Classes)库来实现局域网内的通信以及文件传输。MFC是微软提供的一种C++类库,它封装了Windows API,使得开发者能更容易地创建Windows应用程序...
在本文中,我们将深入探讨如何使用Qt5.9框架实现TCP通信和文件传输。Qt是一个跨平台的应用程序开发框架,广泛应用于GUI编程,同时也支持网络编程。以下将详细阐述相关知识点: 1. **TCP(Transmission Control ...