• Android版Web服务器实现(二)使用服务来监听HTTP请求》一文实现了HTTP请求的监听,那么我们要如何作出响应呢?在响应时,有几种情况。 1、请求的方法不支持。比如服务端仅支持了GET/POST方法,而请求却有DELETE等,...

    Android版Web服务器实现(二)使用服务来监听HTTP请求》一文实现了HTTP请求的监听,那么我们要如何作出响应呢?在响应时,有几种情况。

    1、请求的方法不支持。比如服务端仅支持了GET/POST方法,而请求却有DELETE等,此时回复501。

    2、请求的资源不存在。在服务端不存在该资源文件,将回复404页面。

    3、请求的类型不支持。服务端可能存在该资源,但是该资源的类型没有支持,将回复404.7。

    4、请求正常。服务端将相应的资源回复给客户端。

    5、其他情况。

    下面是依据这些情况的代码实现。

    SessionThread.java

    package com.sparkle.webservice;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    import android.util.Log;
    
    public class SessionThread extends Thread {
    
    	private Socket _clientSocket = null;
    	private final int BUFFER_MAX = 8192;
    	private DataHandle _dataHandle = null;
    	private MyLog _myLog = new MyLog(getClass().getName());
    
    	public SessionThread(Socket clientSocket) {
    		this._clientSocket = clientSocket;
    	}
    
    	public void closeSocket() {
    		if (_clientSocket == null) {
    			return;
    		}
    		try {
    			_clientSocket.close();
    		} catch (IOException e) {
    			_myLog.e(e.getMessage());
    		}
    	}
    
    	public void run() {
    		try {
    
    			InputStream socketInput = _clientSocket.getInputStream();
    			byte[] buffer = new byte[BUFFER_MAX];
    			socketInput.read(buffer);
    			_dataHandle = new DataHandle(buffer);
    			byte[] content = _dataHandle.fetchContent();
    
    			sendResponse(_clientSocket, content);
    
    		} catch (Exception e) {
    			_myLog.l(Log.DEBUG, "Exception in TcpListener");
    		}
    	}
    
    	private void sendResponse(Socket clientSocket, byte[] content) {
    		try {
    			OutputStream socketOut = clientSocket.getOutputStream();
    
    			byte[] header = _dataHandle.fetchHeader(content.length);
    
    			socketOut.write(header);
    			socketOut.write(content);
    
    			socketOut.close();
    			clientSocket.close();
    		} catch (Exception e) {
    		}
    	}
    
    }
    
    注:

    1、在收到请求后,新建一个SessionThread来处理请求(在上一篇中有说到)。

    2、SessionThread建立后,在run中新建DataHandle来处理数据,具体请参看后文代码。

    3、在sendResponse来回应请求。

    4、在响应时,先发送header,再发送content来响应

    DataHandle.java

    package com.sparkle.webservice;
    
    import java.io.UnsupportedEncodingException;
    
    import com.sparkle.io.FileSp;
    
    import android.annotation.SuppressLint;
    import android.util.Log;
    
    public class DataHandle {
    
    	private String _receiveInfo = "";
    	private HttpHeader _httpHeader = null;
    	private String _encoding = "utf-8";
    	private String _serverName = "Simple Web Server";
    	private String _responseCode = "200 OK";
    	private String _contentType = "text/html";
    
    	public DataHandle(byte[] recieveData) {
    		try {
    			this._receiveInfo = new String(recieveData, _encoding);
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		_httpHeader = new HttpHeader(_receiveInfo);
    	}
    
    	public byte[] fetchContent() {
    		byte[] backData = null;
    		if (!isSupportMethod()) {
    			backData = fetchNotSupportMethodBack();
    			return backData;
    		}
    
    		String filePath = fetchFilePath();
    		boolean hasFile=FileSp.isExist(filePath);
    		Log.e("FilePath", filePath+"   "+hasFile);
    		if (!hasFile) {
    			backData = fetchNotFoundBack();
    			return backData;
    		}
    
    		if (!isSupportExtension()) {
    			backData = fetchNotSupportFileBack();
    			return backData;
    		}
    
    		backData = fetchBackFromFile(filePath);
    		return backData;
    	}
    
    	public byte[] fetchHeader(int contentLength) {
    		byte[] header = null;
    		try {
    			header = ("HTTP/1.1 " + _responseCode + "\r\n" 
    					+ "Server: "+ _serverName + "\r\n" 
    					+ "Content-Length: " + contentLength+ "\r\n"
    					+ "Connection: close\r\n" 
    					+ "Content-Type: "+ _contentType + ";charset="+_encoding+"\r\n\r\n").getBytes(_encoding);
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return header;
    	}
    
    	@SuppressLint("DefaultLocale")
    	private boolean isSupportMethod() {
    		String method = _httpHeader.getMethod();
    		if (method == null || method.length() <= 0) {
    			return false;
    		}
    		method = method.toUpperCase();
    		if (method.equals("GET") || method.equals("POST")) {
    			return true;
    		}
    
    		return false;
    	}
    
    	private boolean isSupportExtension() {
    		String contentType = _httpHeader.getContentType();
    		if (contentType == null || contentType.length() <= 0) {
    			return false;
    		}
    		_contentType=contentType;
    		return true;
    	}
    
    	private byte[] fetchNotSupportMethodBack() {
    		byte[] backData = null;
    		String notImplementMethod = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><h2>"
    				+ _serverName
    				+ "</h2><div>501 - Method Not Implemented</div></body></html>";
    		try {
    			backData = notImplementMethod.getBytes(_encoding);
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return backData;
    	}
    
    	private byte[] fetchNotSupportFileBack() {
    		byte[] backData = null;
    		String notImplementMethod = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><h2>"
    				+ _serverName
    				+ "</h2><div>404.7 Not Found(Type Not Support)</div></body></html>";
    		try {
    			backData = notImplementMethod.getBytes(_encoding);
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return backData;
    	}
    
    	private byte[] fetchBackFromFile(String filePath) {
    
    		byte[] content = null;
    
    		content = FileSp.read(filePath);
    		return content;
    	}
    
    	private String fetchFilePath() {
    		String root = Defaults.getRoot();
    	
    		String fileName = _httpHeader.getFileName();
    		String filePath = "";
    
    		if (fileName.startsWith("/") || fileName.startsWith("\\")) {
    			filePath = root + fileName.substring(1);
    		} else {
    			filePath = root + fileName;
    		}
    
    		return filePath;
    	}
    
    	private byte[] fetchNotFoundBack() {
    		byte[] notFoundData = null;
    		String notFoundStr = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><h2>"
    				+ _serverName + "</h2><div>404 - Not Found</div></body></html>";
    		try {
    			notFoundData = notFoundStr.getBytes(_encoding);
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return notFoundData;
    	}
    }
    
    注:

    1、isSupportMethod判断是否是支持的方法,如果不支持,从fetchNotSupportMethodBack获取数据进行响应。

    2、判断请求的资源是否存在,如果不存在,从fetchNotFoundBack获取数据进行响应。

    3、isSupportExtension判断是否是支持的数据类型,如果不支持,从fetchNotSupportFileBack获取数据进行响应。

    4、请求方法支持、请求资源存在,且请求类型支持,将从fetchBackFromFile获取数据进行响应。

    在对HTTP作出相应的响应之后,现在就剩下如果在界面中实现相应的控制了,具体请看下一篇。

    转载请注明出处:Android版Web服务器实现(三)HTTP响应

    源码下载

    展开全文
  • 不,应该是这几天都在弄的登录响应问题,连接一直有问题: 1、首先是服务器一直接收不到我传递过去的数据,是因为我的Person类中没有toString()方法,值根本没传过去。 2、移动端显示响应代码为400,是因为我的...

    不,应该是这几天都在弄的登录响应问题,连接一直有问题:

    1、首先是服务器一直接收不到我传递过去的数据,是因为我的Person类中没有toString()方法,值根本没传过去。

    2、移动端显示响应代码为400,是因为我的Person类中的toString()格式有问题,百度了很久说是Tomcat版本的问题,有些符号被认为是不安全的,所以服务器不能识别移动端传递的数据:

    我写的是:

    @Override
        public String toString() {
            return "Person [id=" + id + ", password=" + password + "]";
        }

    或者:

    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    应该为:

    @Override
    public String toString() {
        return "id="+id+"&password="+ password;
    }

    3、服务器端的那个mysql的包没导,导致一直没连上数据库,这个我检查了3个小时一直在纠结为啥代码不往下执行了呢,看来还是生疏的原因,发现的时候简直气哭,简直太丢脸了。。。。。。。。。

    还有一个原因,如果导了包还是不执行,那就是电脑的Mysql服务在不知什么时候给关了,可以开启,这个时候直接打开mysql的命令窗口后输入密码可能会闪退,解决办法:我的电脑——》管理——》服务和应用程序——》服务——》找到mysql——》点击启动此服务

    4、服务器端报错Allocate exception for servlet [teacherstudent]
    java.lang.ClassNotFoundException: Servlet.teacherstudent

    原来是因为我之前向项目里面导了一些jar包,然后又把它给删了,虽然项目名字上爆红的感叹号,但是没有管,解决办法:点击项目——》选择Porperties——》Java Build Path——》Libraries——》将爆红的jar包给remove掉

    百度上也有解决办法,一般是web.xml中的class文件的路径错误,我检查了一下,发现自己的没有错。

    展开全文
  • 新手小白最近在一个课程项目: 1.手机端(基于android)发送数据到云服务器端 2.服务器端记录数据至数据库 3.手机端再访问服务器端网页,可以在网页上看到表格,表格里是之前发送的数据 我知道在大神们眼里这项目...
  • Android web服务器

    2019-12-05 16:14:06
    要确定其发布页面的语言就要找到他发布的服务器中页面所在的位置,之前说服务器需要存储卡才可以发布服务,所以目标锁定在Android文件系统的sd卡。 打开eclipse,然后启动虚拟机,找到虚拟机的文件管理器,如图 ...

    一、I-jetty的web应用程序编程语言的确定。

    • 要确定其发布页面的语言就要找到他发布的服务器中页面所在的位置,之前说服务器需要存储卡才可以发布服务,所以目标锁定在Android文件系统的sd卡。
    • 打开eclipse,然后启动虚拟机,找到虚拟机的文件管理器,如图
    • 找到mnt/sdcard目录,查看文件夹发现多了两个目录,且都跟jetty有关。在jetty文件夹下发现了webapps,仔细研究发现这个目录类似于之前做过的jsp的目录,再看其文件类型,可以确定这些是jsp项目的页面:
    • 上面的网站文件是编译好的,均为class文件,无法查看其源码,是否采用了其他的自定义的类还不是很清楚,但可以看到他引入了一些jar包,在webapps-console-webinf-lib文件夹下
      目前还有一些问题有待研究,就是1.他开发网站采用的工具是什么,是不是也是跟jsp一样使用myeclipse进行开发,除了引入那些jar包外是否需要安装其他的插件。2.他的网站是如何部署到服务器上去的,例子中的网站是提供了一个apk的安装包,这个安装包要怎么打?或者不用安装包像jsp网站那样直接复制到webapps的目录下是否可以使用?

    二、关于jetty服务器的详细介绍

    看i-jetty的介绍可以了解他是pc端jetty服务器的简化版,我们有必要理解一下jetty服务器是什么,过去的一段时间里jetty服务器一度很火,听说谷歌就是用的jetty的服务器。下面我们了解一下jetty服务器。

    • Jetty
    • Jetty是什么?
    • Jetty是一个用Java实现的开源的Http和Web服务器,包括HTTPserver, HTTPclient和javax.servlet container。
    • Jetty用在何处?
    • Jetty的应用非常广泛,包括:
      · 大型集群系统,如Yahoo HadoopCluster(http://developer.yahoo.net/hadoop/)
      · 云计算服务,如GoogleAppEngine (http://code.google.com/appengine/)
      · SaaS(Software-as-a-service)系统,如Yahoo! Zimbra(http://www.zimbra.com/)
      · 应用程序服务器,如Apache Geronimo(http://geronimo.apache.org/)
      · 应用框架,如GWT(http://code.google.com/webtoolkit/)
      · 工具,如 EclipseIDE(http://www.eclipse.org/)
      · 移动设备,i-jetty(http://code.google.com/p/i-jetty/)
      Jetty的特性是什么?
      Jetty的广泛应用得益于其诸多优秀的特性:
      · 轻量级:Jetty体积小巧,占用系统资源较少。
      · 易嵌入性:Jetty既可以像tomcat一样独立运行,也可以很方便的嵌入到工具、框架或其他应用服务器中运行。Jetty在设计之 初就是作为一个可以嵌入到其他的Java代码中的servlet容器而设计的,因此开发小组将Jetty作为一组Jar文件提供出来,可以非常方便的在自 己的容器中将Jetty实例化成一个对象并操纵该容器对象。
      · 灵活性:Jetty的体系架构及其面向接口的设计实现了功能模块高度可插拔和可扩展的特性,可以非常方便的根据需要来配置Jetty启用的功能。
      · 稳定性:Jetty运行速度较快,即使有大量服务请求并发的情况下,系统性能也能保持在一个可以接受的状态。
      Jetty的体系架构
      下面分别对上图中的几个部分作简要介绍:

    · Connector负责解析服务器请求并产生应答,不同的Connector用于处理不同协议的请求。

    · Handler用于处理经过Connector解析的请求并产生应答内容,同样可以通过配置不同的Handler来负责处理不同的请求。

    · TheadPool:管理和调度多个线程,用于服务于多个连接请求。

    · Server代表一个Jetty服务器对象,主要作用是协同Connector、Handler和TheadPool的工作。

    其中,!TheadPool可以根据配置选择是否使用,Connector和Handler也可以通过配置非常方便的实现替换。

    Continuation机制 ¶

    Continuation机制是Jetty用于更好的支持异步Servlet的机制。

    首先简要介绍一下技术应用的背景。异步请求是指当客户端发送一个请求到服务器的时候,客户端不必一直等待服务器的响应,例如Web 2.0中的Ajax(Asynchronous JavaScript and XML)技术、JDBC连接池等,当服务器端响应返回时,客户端利用一个 Javascript 函数对返回值进行处理,以更新页面上的部分元素的值而不必刷新整个页面,从而带来更好的客户体验。但很多时候这种异步事件只是在很小一部分的情况下才会发生,那么怎么保证一旦服务器端有了响应之后客户端马上就知道呢,我们有两种方法来解决这个问题,一是让浏览器每隔几秒请求服务器来获得更改,称之为轮询。二是服务器维持与浏览器的长时间的连接来传递数据,长连接的技术称之为Comet。轮询的主要缺点是产生了大量的传输浪费;而如果使用Comet技术的话,客户端和服务器端之间必须保持一个长连接,一般来讲,服务器端的一个Servlet会独占一个线程,如果有大量客户端维持长连接,会给服务器端的处理能力带来很大的挑战。

    针对上述情况,Jetty利用Java语言的非堵塞I/O技术来处理并发的大量连接。具体说来,Jetty实现了一个基于java.nioAPI 的SelectChannelConnector,允许它维持每个连接开放而不用消耗一个线程。当连接挂起时,Connector将请求维持在未决 Continuations队列里,用来服务请求的线程返回给TheadPool,这样,该线程又可以服务于其他请求。暂停的请求停留在未决 Continuations 队列里直到指定的过期时间,或者在它的Continuation上调用resume()方法。

    Jetty Vs Tomcat ¶

    Tomcat作为第一款成功的web容器,具有广大的用户群体。从表面功能上Jetty和Tomcat都是差不多的,都提供Http Server和Servlet容器功能,下面我们从几个方面比较两者的差异:

    1. 从构架方面
      Tomcat主要是作为JSP/Servlet最新规范的参考实现而设计,属于学 院派,但是显得庞大而杂乱。最常见的Tomcat使用方式是将其作为一个服务器软件安装到操作系统上,然后在里面部署web应用,如果嵌入到其他JEE服 务器中以提供Web容器功能或者作为组件嵌入到其他应用中,操作起来比较麻烦。
      Jetty是由多个可以独立运行的构件通过彼此之间可插拔的接口组装在一起,其使用可以非常灵活。目前,Jetty在Geronimo、JBoss、Sybase EAServer、JOnAS和Glassfish等JEE应用服务器中提供Web容器功能。

    2. 从性能方面
      Tomcat在耗时请求连接数量不多时,也就是大多数请求能非常短的时间处理完毕的情况下,具有较好的执行效率。
      Jetty 在存在大量并发连接,大多数连接又需要更多的处理时间(业务逻辑计算占用的时间)的情况下(这种情况是目前大多数web应用具有的特点),具有更好的性能 和伸缩性。Jetty的这个优势得益于Continuation机制,这样可以把有限的内存资源更多的留给应用程序使用。在静态文件服务方面,Jetty 也具有更好的性能。这是由于Jetty使用了文件内存映射机制和NIO来对静态内容进行输入输出,这种方式将占用更少的系统内存和更快发送速度。

    3. 从标准规范方面
      Tomcat曾是sevlet2.4规范的参考实现,从Servlet2.5之后,Tomcat不再是参考实现了,Sun公司自己创建了Glassfish,并作为Servlet2.5、Servlet3.0、Jsp2.1的参考实现。
      Jetty在执行规范方面做的非常好,是Servlet2.5规范的一个优秀实现。在Servlet3.0中,Jetty自有的continuation机制也成为规范备选方案之一。

    参考资料 ¶

    1. http://www.ibm.com/developerworks/cn/web/wa-lo-jetty/

    2. http://docs.codehaus.org/display/JETTY/Jetty+Wiki

    三、确定开发工具
    由以上说明可以确定,jetty的项目是通过eclipse+jetty服务器开发,而eclipse和jetty都是跨平台开发工具,且均为免费使用,是开发项目工具的首选,而且不用在乎开发所在的平台是windows还是Linux。jetty本身是一个servlet容器,可以发布servlet项目,同时也支持jsp项目,但对jsp支持不是很好。Jetty服务器还有一个好处就是可以把发布在tomcat里的jsp和servlet项目稍作修改进行发布,实际效果怎样还需要测试才能知道。

    展开全文
  • Android基础入门教程——7.1.2 Android Http请求头与响应头的学习标签(空格分隔): Android基础入门教程本节引言: 上节中我们对Android涉及的网络编程进行了了解,也学习了下Http的基本概念,而本节我们 要...

    Android基础入门教程——7.1.2 Android Http请求头与响应头的学习

    标签(空格分隔): Android基础入门教程


    本节引言:

    上节中我们对Android涉及的网络编程进行了了解,也学习了下Http的基本概念,而本节我们
    要学习的是Http的请求头与响应头,当然,可以把也可以把这节看作文档,用到的时候来查查
    即可!


    1.HTTP请求之消息头:

    这里贴下上一节给出的图,根据下面给出的表,大家自己感受下相关请求头的作用吧:
    PS:第一行是请求行:请求方式 + 资源名称 + HTTP协议版本号,另外请求头只是给服务端的一个
    信息而已或者说一个简单,至于怎么处理,还是由服务端来决定的!


    HTTP Request Header请求头信息对照表:

    Header 解释 示例
    Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
    Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
    Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
    Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
    Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
    Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
    Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
    Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
    Content-Length 请求的内容长度 Content-Length: 348
    Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
    Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
    Expect 请求的特定的服务器行为 Expect: 100-continue
    From 发出请求的用户的Email From: user@email.com
    Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
    If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
    If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
    If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
    If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
    If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
    Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
    Pragma 用来包含实现特定的指令 Pragma: no-cache
    Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Range 只请求实体的一部分,指定范围 Range: bytes=500-999
    Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://blog.csdn.net/coder_pig
    TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
    Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
    User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
    Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
    Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning

    2.HTTP响应之响应头:

    同样给出上节的图:
    PS:第一行依次是:协议版本号 状态码 302表示这里没有,但是另外一个地方有,通过Location页面重定向了

    HTTP Responses Header 响应头信息对照表:

    Header 解释 示例
    Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
    Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
    Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
    Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
    Content-Encoding web服务器支持的返回内容压缩编码类型 Content-Encoding: gzip
    Content-Language 响应体的语言 Content-Language: en,zh
    Content-Length 响应体的长度 Content-Length: 348
    Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.htm
    Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
    Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
    Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
    Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
    ETag 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
    Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2010 16:00:00 GMT
    Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
    Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location: http://blog.csdn.net/coder_pig
    Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
    Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic

    3.代码验证响应头的作用:

    好了,看了那么多概念的东西,不动动手怎么行呢?是吧,那我们就写一些简单的代码来验证一些
    常用的响应头的作用吧,以便加深我们的了解,这里的话服务端就用最简单的Servlet来实现,如果不会
    Java Web的朋友只需将代码拷一拷,配置下web.xml,把Servlet的类名扣上,比如:

        <servlet>
            <servlet-name>FirstServlet</servlet-name>
            <servlet-class>com.jay.server.FirstServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>FirstServlet</servlet-name>
            <url-pattern>/FirstServlet</url-pattern>
        </servlet-mapping>

    改成对应的类名即可!


    1)通过Location实现页面重定向

    实现代码

    package com.jay.http.test;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletOne extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            //告诉浏览器响应码,以及重定向页面
            resp.setStatus(302);
            resp.setHeader("Location", "http://www.baidu.com");
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            this.doGet(req, resp);
        }
    }
    

    运行结果
    当我们去访问:http://localhost:8080/HttpTest/ServletOne的时候,我们会发现页面跳转到了百度,
    接着我们用FireFox的开发者工具:可以看到我们发出的HTTP的内容:


    2)通过Content-Encoding告诉浏览器数据的压缩格式

    实现代码

    package com.jay.http.test;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.zip.GZIPOutputStream;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletTwo extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            String data = "Fresh air and sunshine can have an amazing effect on our feelings. "
                    + "Sometimes when we are feeling down, all that we need to do is simply to go "
                    + "outside and breathe. Movement and exercise is also a fantastic way to feel better. "
                    + "Positive emotions can be generated by motion. So if we start to feel down,"
                    + " take some deep breathes, go outside, feel the fresh air, "
                    + "let the sun hit our face, go for a hike, a walk, a bike ride, "
                    + "a swim, a run, whatever. We will feel better if we do this.";
            System.out.println("原始数据长度:" + data.getBytes().length);
            // 对数据进行压缩:
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            GZIPOutputStream gout = new GZIPOutputStream(bout);
            gout.write(data.getBytes());
            gout.close();
            // 得到压缩后的数据
            byte gdata[] = bout.toByteArray();
            resp.setHeader("Content-Encoding", "gzip");
            resp.setHeader("Content-Length", gdata.length + "");
            resp.getOutputStream().write(gdata);
    
        }
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            doGet(req, resp);
        };
    }
    

    运行结果

    控制台输出:
    浏览器输出:
    再看看我们的HTTP内容:
    这个gzip压缩字符串对于简单的字符串压缩,效率不高,比如小猪本来写的是一个一首静夜诗的字符串,
    后来发现压缩过后的大小,竟然比原先的还要大=-=…


    3)通过content-type,设置返回的数据类型

    服务端返回的有时可能是一个text/html,有时也可能是一个image/jpeg,又或者是一段视频video/avi
    浏览器可以根据这个对应的数据类型,然后以不同的方式将数据显示出来!好吧,这里我们弄一个读PDF的

    实现代码

    package com.jay.http.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletThree extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setHeader("content-type", "application/pdf");
            InputStream in = this.getServletContext().getResourceAsStream("/file/android编码规范.pdf");
            byte buffer[] = new byte[1024];
            int len = 0;
            OutputStream out = resp.getOutputStream();
            while((len = in.read(buffer)) > 0)
            {
                out.write(buffer,0,len);
            }
        }
    
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws
           ServletException ,IOException 
        {
            doGet(req, resp);
        };
    }
    

    运行结果

    在浏览器上输入:http://localhost:8080/HttpTest/ServletThree
    好哒,果然可以读到PDF了,对了,这个PDF我已经丢在webroot的file目录下,不然会报空指针哦~:
    当然,你也可以试着去播放一段音乐或者视频,只需修改下content-type这个参数而已
    下面顺便给出个HTTP Content-type的对照表吧:


    4)通过refresh响应头,让浏览器隔几秒后跳转至别的页面

    恩呢,一般我们可能有这样的需求,比如每隔几秒刷新一次页面,又或者加载某个页面几秒后
    又跳转至另一个页面,那么refresh可以满足你的需要~

    实现代码

    package com.jay.http.test;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletFour extends HttpServlet {
        public int second = 0;
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            //1.浏览器每隔2秒定时刷新页面
    //      resp.setHeader("refresh", "2");
    //      resp.getWriter().write(++second + "");
    //      System.out.println("doGet方法被调用~");
    
            //2.进入页面5s后,然页跳到百度~
            resp.setHeader("refresh", "5;url='http://www.baidu.com'");
            resp.getWriter().write("HE HE DA~");
        }
    
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException ,IOException 
        {
            doGet(req, resp);
        };
    }
    

    运行结果

    • 1的话每隔2秒刷新一次页面,我们可以看到显示的数字是递增的,另外doGet方法也一直被调用,
      说明页面真的是刷新的!
    • 2的话进入页面后5s,就自己跳转到百度了~

    5)通过content-dispostion响应头,让浏览器下载文件

    这个很简单,我们只需把③中设置Content-type的一行去掉,然后加上:
    resp.setHeader(“content-disposition”, “attachment;filename=Android.pdf”);

    实现代码

    package com.jay.http.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletFive extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            resp.setHeader("content-disposition", "attachment;filename=Android.pdf");
            InputStream in = this.getServletContext().getResourceAsStream("/file/android编码规范.pdf");
            byte buffer[] = new byte[1024];
            int len = 0;
            OutputStream out = resp.getOutputStream();
            while((len = in.read(buffer)) > 0)
            {
                out.write(buffer,0,len);
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

    运行结果


    本节小结:

    本节给大家介绍了Http中的请求头和响应头,也写了几个关于响应头调浏览器的一些示例,
    相信经过本章,大家对于Http协议更加了解了,下节我们来学习Android给我们提供的Http
    请求方式:HttpURLConnection!好的,本节就到这里,谢谢~
    对了,本节demo下载:HttpTest.zip

    展开全文
  • 一直以来对Android socket通信都很模糊,今天终于研究了一个网上的例子,自己又修改了下,算是对Android socket通信有点了解了。 下面是具体的代码,说明都在注释中了。需要注意的是,只有客户端发送了信息给服务器...

    一直以来对Android socket通信都很模糊,今天终于研究了一个网上的例子,自己又修改了下,算是对Android socket通信有点了解了。

    下面是具体的代码,说明都在注释中了。需要注意的是,只有客户端发送了信息给服务器后,服务器才能响应客户端的输入,然后返回信息给客户端,这时客户端才能读取服务器返回的信息。如果客户端和服务器都处于等待对方的信息,那样就会造成阻塞,导致ANR了。

    1.服务器端代码,就是一个java程序,与android无关,运行于服务器上,即PC机上。

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * 测试Android客户端与PC服务器通过socket进行交互
     * 服务器端:接收客户端的信息并回送给客户
     * @author Ameyume
     *
     */
    public class Server implements Runnable {
    	public static final String SERVERIP = "192.168.1.100";
    	public static final int SERVERPORT = 51706;
    
    	public void run() {
    		try {
    			System.out.println("S: Connecting...");
    
    			ServerSocket serverSocket = new ServerSocket(SERVERPORT);
    			while (true) {
    			    // 等待接受客户端请求 
    				Socket client = serverSocket.accept();
    
    				System.out.println("S: Receiving...");
    				
    				try {
    				    // 接受客户端信息
    					BufferedReader in = new BufferedReader(
    							new InputStreamReader(client.getInputStream()));
    					
                        // 发送给客户端的消息 
                        PrintWriter out = new PrintWriter(new BufferedWriter(
                        		new OutputStreamWriter(client.getOutputStream())),true);
                        
                        System.out.println("S: 111111");
                        String str = in.readLine(); // 读取客户端的信息
                        System.out.println("S: 222222");
                        if (str != null ) {
                        	// 设置返回信息,把从客户端接收的信息再返回给客户端
    	                    out.println("You sent to server message is:" + str);
    	                    out.flush();
    	                    
    	                    // 把客户端发送的信息保存到文件中
    	                    File file = new File ("C://android.txt");
    	                    FileOutputStream fops = new FileOutputStream(file); 
    	                    byte [] b = str.getBytes();
    	                    for ( int i = 0 ; i < b.length; i++ )
    	                    {
    	                        fops.write(b[i]);
    	                    }
    						System.out.println("S: Received: '" + str + "'");
                        } else {
                        	System.out.println("Not receiver anything from client!");
                        }
    				} catch (Exception e) {
    					System.out.println("S: Error 1");
    					e.printStackTrace();
    				} finally {
    					client.close();
    					System.out.println("S: Done.");
    				}
    			}
    		} catch (Exception e) {
    			System.out.println("S: Error 2");
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String [] args ) {
    		Thread desktopServerThread = new Thread(new Server());
    		desktopServerThread.start();
    
    	}
    }
    2.客户端程序,运行在手机或者模拟器上。

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    /**
     * 测试Android客户端与PC服务器通过socket进行交互
     * 客户端:把用户输入的信息发送给服务器
     * @author Ameyume
     *
     */
    public class Socket_Android extends Activity {
    	private static final String TAG = "Socket_Android";
    	
    	private EditText mEditText = null;
    	private TextView tx1 = null;
    	private Button mButton = null;
    	
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            
            mButton = (Button)findViewById(R.id.Button01);
            mEditText = (EditText)findViewById(R.id.etSendMsg);
            tx1 = (TextView)findViewById(R.id.tx);
            
            mButton.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View v) {
    				// TODO Auto-generated method stub
    				setTitle("测试Socket连接");
    				Socket socket = null;
    				
    				try {
    					/* 指定Server的IP地址,此地址为局域网地址,如果是使用WIFI上网,则为PC机的WIFI IP地址
    					 * 在ipconfig查看到的IP地址如下:
    					 * Ethernet adapter 无线网络连接:
            			 * Connection-specific DNS Suffix  . : IP Address. . . . . . . . . . . . : 192.168.1.100
    					 */
    					InetAddress serverAddr = InetAddress.getByName("192.168.1.100");// TCPServer.SERVERIP
    					Log.d("TCP", "C: Connecting...");
    					
    					// 应用Server的IP和端口建立Socket对象
                        socket = new Socket(serverAddr, 51706);
                        String message = "---Test_Socket_Android---";  
      
                        Log.d("TCP", "C: Sending: '" + message + "'");  
                        
                        // 将信息通过这个对象来发送给Server  
                        PrintWriter out = new PrintWriter(new BufferedWriter(  
                                new OutputStreamWriter(socket.getOutputStream())),  
                                true);  
                          
                        // 把用户输入的内容发送给server
                        String toServer = mEditText.getText().toString();
                        Log.d(TAG, "To server:'" + toServer + "'");
                        out.println(toServer);
                        out.flush();  
                        
                        
                        // 接收服务器信息  
                        BufferedReader in = new BufferedReader(  
                                    new InputStreamReader(socket.getInputStream()));  
                        // 得到服务器信息  
                        String msg = in.readLine();
                        Log.d(TAG, "From server:'" + msg + "'");
                        // 在页面上进行显示  
                        tx1.setText(msg);  
    				} catch(UnknownHostException e) {
    					Log.e(TAG, "192.168.1.100 is unkown server!");
    				} catch(Exception e) {
    					e.printStackTrace();
    				} finally {
    					try {
    						socket.close();
    					} catch(Exception e) {
    						e.printStackTrace();
    					}
    				}
    			}
            	
            });
        }
    }
    3.在客户端AndroidManifest.xml文件增加访问互联网的权限

    <uses-permission android:name="android.permission.INTERNET" />

    4.运行效果:


    服务器接的log输出:

    S: Receiving...
    S: 111111
    S: 222222
    S: Received: 'hello'
    S: Done.

    本文参考自:Android通过socket连接服务器(PC)



    展开全文
  • android中,有很多的情况都要用到网络的功能,而发送HTTP请求的代码基本上是一样的。所以我觉得很有必要将这些通用的操作提取到一个公共类里,并提供一个静态的方法,当想要发起网络请求的时候只需要简单的调用...
  • Motivation 我写这套帖子的目的,是在自己学会、实现...我在学习编写自己的Android应用程序服务器的时候遇到过以下的问题: 1.我需要准备什么? 2.我该选择哪一套实现方案? …… 这些问题的搜索和查证都...
  • NTP服务器同步android系统时间
  • android充当server服务器

    2016-02-29 10:45:30
    android上跑起来一个web服务器,可供电脑和手机通过http访问。这个需求并不常见,网上资料也不多,找了一会发现了一个不错的框架。github链接地址https://github.com/NanoHttpd/nanohttpd  这个框架使用起来比较...
  • 如何保障android客户端与服务器时间同步,不受用户更改系统时间的影响? NTP协议 NTP原理如下: 系统时钟同步的工作过程如下: Device A发送一个NTP报文给Device B,该报文带有它离开Device A时的时间戳,该...
  • 根据项目需求,需要上传相册和拍照...我们来了解下Android客户端如何通过HTTP协议来将图片上传到服务器。我们先来了解下HTTP multipart/form-data,上传报文格式。 假设接收文件的网页程序是http://172.31.8.6:8080
  • ZERO、前言 有关通信原理内容是在网上或百科...两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双
  • Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度! 算下来,TomCat服务器已经写了很长一段时间了,一直说拿他来搞点事情,也一直没,今天刚好有空,交流群还有人请教,就寻思着把一些...
  • java搭建本地服务器android客户端访问,tomcat详细步骤代码都在这里,先可以不用下这个,跟着下面先把环境搭好,出问题再来看代码:https://download.csdn.net/download/qq_31939617/10275515eclispe64位,直接...
  • 前言:在上一篇博客《Android 拍照、选择图片并裁剪》中主要说明了在Android中图片裁剪的一种方式,当然我们裁剪图片的最终目的是为了上传服务器,最常用的是设置用户头像。即用户在客户端拍照或者选择图片后上传...
  • 基于HttpURLConnection实现android端上传文件到服务器端。
  • 状态码就是告诉我们服务器响应的状态 通过它,我们就可以知道当前请求是成功了还是出现了什么问题 状态码是由3位数字和原因短语组成的(比如最常见的:200 OK) 其中第一位数字表示响应类别,响应类别从1到5分为...
  • 公司临时加的需要,客户想要发送图片,研究了半天,直接发送图片服务器接收总是出问题,无法接收,改变了策略,android端发送图片的byte数组,还是不成功,最后决定用Base64编码后服务器接收.实体类:controller:下图是保存原...
  • Android手机客户端和后台服务器交互(数据库mysql)
1 2 3 4 5 ... 20
收藏数 55,416
精华内容 22,166