Java文件传输报文

记录实习期间学习到的关于 “如何在不同服务器上进行文件处理和传输”(如果我没理解错的话)。要求就是将文件在不同服务端和客户端之间进行传输。若一端发出上传文件请求,可以直接发送给目标服务端,也可以通过某服务端中转。若中转,中转服务端会有中转指令,然后将收到的文件发送给目标服务端。
有部分转载内容,已附转载地址。
以下是学习过程涉及到的知识内容。

SecureCRT软件

是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单地说是Windows下登录UNIX或Linux服务器主机的软件。

HTTP报文格式

1、HTTP报文格式

在开发中,我们使用的比较多的HTTP请求方式基本上就是GET、POST。其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等。而我们在使用HTTP请求时中遇到的比较麻烦的事情就是构造文件上传的HTTP报文格式,这个格式虽说也比较简单,但也比较容易出错。
HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的。是一种 client-server 协议。HTTP有两类报文:请求报文和响应报文。
在这里插入图片描述

Request|Response–>HTTP请求报文格式与响应报文格式

在这里插入图片描述
在这里插入图片描述
\r代表回车,\n代表换行,也就是 CRLF。

上个实例:

请求

POST /index.html HTTP/1.1
HOST: www.XXX.com
User-Agent: Mozilla/5.0(Windows NT 6.1;rv:15.0) Firefox/15.0

Username=admin&password=admin

响应

HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8




    
    Document


    

this is http response

当然上面的是最简单的报文内容,实际上的报文内容肯定比这个复杂。

下面对重要的参数详细解释一下。

1. 请求方式Method:
(1)GET方法意思是获取URL指定的资源,这个请求方式是最简单的也是最常用的。使用GET 方法时,可以将请求参数和对应的值附加在 URI 后面,利用一个问号(“?”)将资源的URI和请求参数隔开,参数之间使用与符号(“&”)隔开,因此传递参数长度也受到了限制,而且与隐私相关的信息也直接暴露在URI中。比如/index.jsp?username=holmofy&password=123123

(2)HEAD 方法与GET用法相同,但没有响应体,使用场合没有GET多。比如下载前使用HEAD发送请求,通过ContentLength响应字段,来了解网络资源的大小;或者通过LastModified响应字段来判断本地缓存资源是否要更新。
(3)POST 方法一般用提交信息或数据,请求服务器进行处理(例如提交表单或者上传文件)。表单使用POST相对GET来说还是比较隐秘的,而且GET的URL有长度限制,而上传大文件就必须要使用POST了。

(4)OPTIONS方法比较少见,该方法用于请求服务器告知其支持哪些其他的功能和方法。通过OPTIONS 方法,可以询问服务器具体支持哪些方法,或者服务器会使用什么样的方法来处理一些特殊资源。可以说这是一个探测性的方法,客户端通过该方法可以在不访问服务器上实际资源的情况下就知道处理该资源的最优方式。这个选项在跨域HTTP请求的情况出现的比较多,这里有一片关于跨域请求的文章,其中有一张图很好的解释了什么是跨域HTTP请求。
(5)PUT:用于向指定资源位置上传其最新内容(原来没有就上传,有就上传并覆盖原来的内容)
(6)DELETE:请求服务器删除Request-URI所标识的资源。
(7)TRACE:回显服务器收到的请求,主要用于测试或诊断。比较少见。
(8)CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。
其中GET和POST是最常用的,其次是HEAD和OPTIONS;像PUT和DELETE属于危险方法,服务器都会关闭;TRACE和CONNECT非常少见。

2.Request-URI
URI 的最常见形式是统一资源定位符 (URL),它也被称为 Web地址。这种网址是我们经常见到的。

http://example.org/absolute/path/resource.txt

在请求的URI中还有一种相对路径的,对于这种请求来说在请求头信息中一般有Host值来指定服务器主机。比如:

GET /Test.jsp HTTP/1.1
...
Host:www.example.com
...

3.Http响应码
客户端发出HTTP请求,服务端接收后,会向客户端发送响应信息,其中HTTP响应中的第一行中,最重要的就是HTTP的状态码。比如:

HTTP/1.0 200 OK

这个状态码是200,表示请求成功。HTTP协议中状态码有三位数字组成,第一位数字定义了响应的类别,有以下五种:

1XX:信息提示。表示请求已被服务器接受,但需要继续处理,范围为100~101。
2XX:请求成功。服务器成功处理了请求。范围为200~206。
3XX:客户端重定向。重定向状态码用于告诉客户端浏览器,它们访问的资源已被移动,并告诉客户端新的资源位置。客户端收到重定向会重新对新资源发起请求。范围为300~305。
4XX:客户端信息错误。客户端可能发送了服务器无法处理的东西,比如请求的格式错误,或者请求了一个不存在的资源。范围为400~415。
5XX:服务器出错。客户端发送了有效的请求,但是服务器自身出现错误,比如Web程序运行出错。范围是500~505。

常见的状态码务必要熟悉:

200:客户端请求成功。

302:重定向。

404:请求资源不存在。

400:请求语法错误,服务器无法理解。

403:服务器收到请求,但拒绝提供服务。

500:服务器内部错误。

503:服务器当前不能处理客户端请求,可能需要一段时间后才能恢复正常。

版权声明:本文为CSDN博主「Holmofy」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/holmofy/article/details/68492045

2.GET与POST区别

HTTP定义了与服务器交互的不同方法,最基本的方法是 GET 和 POST.
HTTP POST的报文格式以及通过Java来模拟文件上传的请求。
HTTP-GET和HTTP-POST是使用HTTP的标准协议动词,用于编码和传送变量名/变量值对参数,并且使用相关的请求语义。每个HTTP-GET和HTTP-POST都由一系列HTTP请求头组成,这些请求头定义了客户端从服务器请求了什么,而响应则是由一系列HTTP应答头和应答数据组成,如果请求成功则返回应答。
  HTTP-GET以使用MIME类型application/x-www-form-urlencoded的urlencoded文本的格式传递参数。Urlencoding是一种字符编码,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。附加参数还能被认为是一个查询字符串。
  与HTTP-GET类似,HTTP-POST参数也是被URL编码的。然而,变量名/变量值不作为URL的一部分被传送,而是放在实际的HTTP请求消息内部被传送。

(1)get是从服务器上获取数据,post是向服务器传送数据。

(1) 在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交。

(2) 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。

(2) GET方式提交的数据最多只能有1024字节,而POST则没有此限制。

(3) 安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。

注:所谓安全的意味着该操作用于获取信息而非修改信息。幂等的意味着对同一 URL 的多个请求应该返回同样的结果。完整的定义并不像看起来那样严格。换句话说,GET 请求一般不应产生副作用。从根本上讲,其目标是当用户打开一个链接时,她可以确信从自身的角度来看没有改变资源。比如,新闻站点的头版不断更新。虽然第二次请求会返回不同的一批新闻,该操作仍然被认为是安全的和幂等的,因为它总是返回当前的新闻。反之亦然。POST 请求就不那么轻松了。POST 表示可能改变服务器上的资源的请求。仍然以新闻站点为例,读者对文章的注解应该通过 POST 请求实现,因为在注解提交之后站点已经不同了(比方说文章下面出现一条注解)。

下面举一个简单的例子来说明它们的区别:

 


<% If Request.QueryString("Text") <> "" Then %>

通过get方式传递的字符串是:

"<%= Request.QueryString("Text") %>"
<% End If %> <% If Request.Form("Text") <> "" Then %>

通过Post方式传递的字符串是:

 "<%= Request.Form("Text") %>"
<% End If %>

Java实现服务端和客户端文件传输

Java文件传输报文_第1张图片
实现思路
一、客户端发文件:首先建立和服务器的连接,然后我们通过IO流来实现数据的传输,步骤:
1、通过服务器的IP地址和端口号实现和服务器的连接(这里不要忘记先开服务器哦)
2、获取本地的文件的地址,建立java和文件的连接。
3、获取文件输入流和数据输出流(注意:这里的输入和输出都是指对于java,文件输入流的对象名可以为fis,数据输出流的对象名可以为dos;反之,文件输出流fos,数据输入流dis,即和前者相反的过程)
4、写文件。
二、服务器收文件:
1、接收客户端建立连接的申请,生成一个socket对象。
2、赋予一个服务器端的文件地址(之后在写数据的时候如果文件不存在,则自动创建文件并写数据,若存在文件,则会覆盖原文件,如果要不覆盖可以这样改:fos = new FileOutputStream(file,true);)
3、获取数据输入流和文件输出流。
4、读文件。

代码实现
我在代码中实现了先发一段字符串再发一个完整的文件,文件前的字符串作为文件附带信息,作为文件的信息补充。在聊天室的编写中,可以用来补充文件的发送者和接受者信息。
1、客户端:

public class Client {    
	 public static void main(String[] args){
	int length =0;
	FileInputStream fis = null;
        DataOutputStream dos = null;
        Socket socket = null; 
        OutputStream out =null;
        PrintWriter pw = null;
        byte[] sendByte = null;
		 try {
			socket = new Socket("localhost",7777);
			out = socket.getOutputStream();
			pw = new PrintWriter(out);
			System.out.println("连接到服务器成功");
			File file = new File("E:\\workspace\\mayifan\\src\\com\\myf\\clientTest1207\\tree.zip");
			fis = new FileInputStream(file);
			dos = new DataOutputStream(socket.getOutputStream());
			sendByte = new byte[1024];			
			pw.write("123"+"\r\n");
			pw.flush();
			pw.write("456"+"\r\n");
			pw.flush();			
			System.out.println("准备发送");
			while((length=fis.read(sendByte))>0){				
				dos.write(sendByte, 0 , length);
				dos.flush();
			}
			System.out.println("文件发送完毕");						
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				fis.close();
				dos.close();
			        socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
		}		 		 
	 }		
}

2、服务端

public class Server {
	 public static void main(String[] args){
		 DataInputStream dis=null;
		 Socket socket =null;
		 FileOutputStream fos =null;
		 InputStreamReader ir = null;
		 BufferedReader br = null;
		 try{
		    int length=0;
		    byte[] getByte = new byte[1024];		
		    ServerSocket ss = new ServerSocket(7777);
		    System.out.println("服务器创建完毕");
		    socket = ss.accept();
		    ir=new InputStreamReader(socket.getInputStream());
		    br=new BufferedReader(ir);			
		    System.out.println("连接到客户端");
		    dis = new DataInputStream(socket.getInputStream());
		    File file = new File("E:\\workspace\\mayifan\\src\\com\\myf\\serverTest1207\\tree1.zip");
		    fos = new FileOutputStream(file);		
	            String first = br.readLine();
	            String second = br.readLine();        
	            System.out.println(first);
	            System.out.println(second);						
                    System.out.println("准备接收文件");
			while((length=dis.read(getByte))>0){				
				fos.write(getByte, 0, length);
				fos.flush();
			}
	            System.out.println("文件接收完毕");	       	        	        
		 }catch(IOException e){
			 e.getStackTrace();
		 }finally{
			 try {
				dis.close();
				fos.close();
			        socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
		 }		 
	 }	 	 
}

大家在使用时,注意修改文件的源地址和目标地址。


版权声明:本文为CSDN博主「mayifan_blog」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mayifan_blog/article/details/84896877

你可能感兴趣的:(Java,计算机网络)