1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Java Socket发送与接收HTTP消息简单实现

Java Socket发送与接收HTTP消息简单实现

时间:2021-09-01 20:51:21

相关推荐

Java Socket发送与接收HTTP消息简单实现

在上次Java Socket现实简单的HTTP服务我 们实现了简单的HTTP服务,它可以用来模拟HTTP服务,用它可以截获HTTP请求的原始码流,让我们很清楚的了解到我们向服务发的HTTP消息的结 构,对HTTP请求消息有个清晰的认识。这一节我想写了一个客户的程序,就是用来模拟浏览器,用来向服务器发送HTTP请求,最得要的是可以用它来显示服 务器发回来的HTTP响应消息的一般结构。

[java]view plaincopy importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStreamWriter;.InetAddress;.Socket;.UnknownHostException;importjava.util.ArrayList;/***一个简单的HTTP客户端,发送HTTP请求,模拟浏览器*可打印服务器发送过来的HTTP消息*/publicclassSimpleHttpClient{privatestaticStringencoding="GBK";publicstaticvoidmain(String[]args){try{Sockets=newSocket(InetAddress.getLocalHost(),8080);OutputStreamWriterosw=newOutputStreamWriter(s.getOutputStream());StringBuffersb=newStringBuffer();sb.append("GET/HttpStream/gb2312.jspHTTP/1.1\r\n");sb.append("Host:localhost:8088\r\n");sb.append("Connection:Keep-Alive\r\n");//注,这是关键的关键,忘了这里让我搞了半个小时。这里一定要一个回车换行,表示消息头完,不然服务器会等待sb.append("\r\n");osw.write(sb.toString());osw.flush();//--输出服务器传回的消息的头信息InputStreamis=s.getInputStream();Stringline=null;intcontentLength=0;//服务器发送回来的消息长度//读取所有服务器发送过来的请求参数头部信息do{line=readLine(is,0);//如果有Content-Length消息头时取出if(line.startsWith("Content-Length")){contentLength=Integer.parseInt(line.split(":")[1].trim());}//打印请求部信息System.out.print(line);//如果遇到了一个单独的回车换行,则表示请求头结束}while(!line.equals("\r\n"));//--输消息的体System.out.print(readLine(is,contentLength));//关闭流is.close();}catch(UnknownHostExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}/**这里我们自己模拟读取一行,因为如果使用API中的BufferedReader时,它是读取到一个回车换行后*才返回,否则如果没有读取,则一直阻塞,直接服务器超时自动关闭为止,如果此时还使用BufferedReader*来读时,因为读到最后一行时,最后一行后不会有回车换行符,所以就会等待。如果使用服务器发送回来的*消息头里的Content-Length来截取消息体,这样就不会阻塞**contentLe参数如果为0时,表示读头,读时我们还是一行一行的返回;如果不为0,表示读消息体,*时我们根据消息体的长度来读完消息体后,客户端自动关闭流,这样不用先到服务器超时来关闭。*/privatestaticStringreadLine(InputStreamis,intcontentLe)throwsIOException{ArrayListlineByteList=newArrayList();bytereadByte;inttotal=0;if(contentLe!=0){do{readByte=(byte)is.read();lineByteList.add(Byte.valueOf(readByte));total++;}while(total<contentLe);//消息体读还未读完}else{do{readByte=(byte)is.read();lineByteList.add(Byte.valueOf(readByte));}while(readByte!=10);}byte[]tmpByteArr=newbyte[lineByteList.size()];for(inti=0;i<lineByteList.size();i++){tmpByteArr[i]=((Byte)lineByteList.get(i)).byteValue();}lineByteList.clear();returnnewString(tmpByteArr,encoding);}}

运行时访问一个页面打印如下:

下面来个文件下载的看怎么样?

请求的Jsp页面如下:

[java]view plaincopy <%@pageimport="java.io.InputStream"contentType="text/html;charset=GB2312"%><%@pageimport="java.io.FileInputStream"%><%@pageimport="java.io.OutputStream"%><html><body><br><%try{InputStreamis=newFileInputStream("e:/tmp/file2.txt");OutputStreamos=response.getOutputStream();byte[]readContent=newbyte[1024];intreadCount=0;while(is.available()>0){readCount=is.read(readContent);os.write(readContent,0,readCount);}is.close();//注这里一定要关闭,不然的话抛异常,异常请见下面,原因就是response.getWriter()//与response.getOutputStream()不能同时使用,如果在这里关闭了,前面与后面向//out对象里写的数据就不会刷新到客户端了,只有向response.getOutputStream()写的//数据会输出到客户端。os.close();}catch(Exceptione){e.printStackTrace();}%></body></html>

如里上面Jsp下载页面中的 os.close() 注释掉的话会抛如下异常:

exception

org.apache.jasper.JasperException: getOutputStream() has already been called for this responseorg.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:476)org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:383)org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

root cause

java.lang.IllegalStateException: getOutputStream() has already been called for this responseorg.apache.catalina.connector.Response.getWriter(Response.java:601)org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:196)org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:185)org.apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.java:116)org.apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.java:76)org.apache.jsp.gb2312_jsp._jspService(gb2312_jsp.java:78)org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)javax.servlet.http.HttpServlet.service(HttpServlet.java:803)org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

以下是服务器经过编译生成的servlet类文件:

[java]view plaincopy packageorg.apache.jsp;importjavax.servlet.*;importjavax.servlet.http.*;importjavax.servlet.jsp.*;importjava.io.InputStream;importjava.io.FileInputStream;importjava.io.OutputStream;publicfinalclassgb2312_jspextendsorg.apache.jasper.runtime.HttpJspBaseimplementsorg.apache.jasper.runtime.JspSourceDependent{privatestaticjava.util.List_jspx_dependants;publicObjectgetDependants(){return_jspx_dependants;}publicvoid_jspService(HttpServletRequestrequest,HttpServletResponseresponse)throwsjava.io.IOException,ServletException{JspFactory_jspxFactory=null;PageContextpageContext=null;HttpSessionsession=null;ServletContextapplication=null;ServletConfigconfig=null;JspWriterout=null;Objectpage=this;JspWriter_jspx_out=null;PageContext_jspx_page_context=null;try{_jspxFactory=JspFactory.getDefaultFactory();response.setContentType("text/html;charset=GB2312");pageContext=_jspxFactory.getPageContext(this,request,response,null,true,8192,true);_jspx_page_context=pageContext;application=pageContext.getServletContext();config=pageContext.getServletConfig();session=pageContext.getSession();out=pageContext.getOut();_jspx_out=out;out.write("\r\n");out.write("\r\n");out.write("\r\n");out.write("<html>\r\n");out.write("\t<body><br>\r\n");out.write("\t\t");try{InputStreamis=newFileInputStream("e:/tmp/file2.txt");OutputStreamos=response.getOutputStream();byte[]readContent=newbyte[1024];intreadCount=0;while(is.available()>0){readCount=is.read(readContent);os.write(readContent,0,readCount);}is.close();//注这里一定要关闭,不然的话抛异常,异常请见下面,原因就是response.getWriter()//与response.getOutputStream()不能同时使用,如果在这里关闭了,前面与后面向//out对象里写的数据就不会刷新到客户端了,只有向response.getOutputStream()写的//数据会输出到客户端。os.close();}catch(Exceptione){e.printStackTrace();}out.write("\r\n");out.write("\t</body>\r\n");out.write("</html>");}catch(Throwablet){if(!(tinstanceofSkipPageException)){out=_jspx_out;if(out!=null&&out.getBufferSize()!=0)out.clearBuffer();if(_jspx_page_context!=null)_jspx_page_context.handlePageException(t);}}finally{if(_jspxFactory!=null)_jspxFactory.releasePageContext(_jspx_page_context);}}}

最后是服务向客户端输出的码流如下:

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Set-Cookie: JSESSIONID=328097D70C625E8A9279FF9472319A5D; Path=/HttpStream

Content-Type: text/html;charset=GB2312

Content-Length: 60

Date: Mon, 09 Nov 13:19:22 GMT

这是测试文件的内容:

中a ~!@#$%^&*()_+{}|:\" <>?`-=[]\\;',./

原文:/a9529lty/article/details/7174265

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。