章前准备
ServerSocket使用简介:
jdk描述:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
关键方法:1.ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
2.accept() 侦听并接受到此套接字的连接。
使用总结:建立ServerSocket后,通过accept不断获取Socket,并对获取的Socket进行数据的接收分析,和发送
Socket使用简介:
jdk描述:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
关键方法:1.getInputStream() 返回此套接字的输入流。
2.getOutputStream() 返回此套接字的输出流。
使用总结:建立Socket后,通过输入流传入请求数据,通过输出流获取响应数据,这里获取的全是字节流(小心乱码哦,亲)- -
简单测试一:我们要建立连接
/** * @author 程猿 * 简单的创建了一个ServerSocket,观察使用方式 * */ public class Server { public static void main(String args[])throws Exception { ServerSocket server = new ServerSocket(8080); while (true) { Socket socket = server.accept(); System.out.println("获取新的socket"); } } }
/** * @author 程猿 * 创建Socket后即可进行与相应的服务端进行连接 */ public class Client { public static void main(String args[]) throws Exception { Socket socket = new Socket("127.0.0.1", 8080); } }
启动Server后不断启动Client就会不断地打印出获取新的socket,可见Socket在新建时就已经尝试开始链接了,可以发现ServerSocket和Socket的一一对应仅仅跟地址,端口号相关
虽然能够连接具有跨时代的意义,不过我还更在乎他们之间如何进行数据的交互/通信
简单测试二:我们要让链接可以通信
/** * * @author 程猿 * * 尝试使用输入输出流进行数据的接受与发送 * InputStream:当对方中断后,我们才会停止,跳出 */ public class Server { public static void main(String args[])throws Exception { ServerSocket server = new ServerSocket(8080); while (true) { Socket socket = server.accept(); System.out.println("get a socket"); //接受请求 InputStream inputStream = socket.getInputStream(); int i=0; while((i=inputStream.read())!=-1){ System.out.print((char)i); } //发送回应 OutputStream outputStream = socket.getOutputStream(); outputStream.write("imok".getBytes()); socket.close(); System.out.println(); System.out.println("socket is over"); } } }
/** * @author 程猿 * 因为服务端以(i=inputStream.read())!=-1为请求结束依据,在客户端就必须尝试关闭相应的OutputStream * 当然,直接关闭OutputStream会产生连锁问题...比如socket和InputStream都被关闭 * 故使用了socket提供的单独关闭的方法... */ public class Client { public static void main(String args[]) throws Exception { Socket socket = new Socket("127.0.0.1", 8080); OutputStream outputStream = socket.getOutputStream(); outputStream.write("hry".getBytes()); socket.shutdownOutput(); // outputStream.close(); InputStream inputStream = socket.getInputStream(); int i=0; while((i=inputStream.read())!=-1){ System.out.print((char)i); } } }
打开服务端
1.点击测试二的Client,服务端会显示
get a socket
hry
socket is ove
2.开浏览器,输入127.0.0.1:8080,服务端显示:
get a socket GET / HTTP/1.1 Host: 127.0.0.1:8080 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: JSESSIONID=C8CD6B63C4FC2C05A3CA48D667F4A484 Connection: keep-alive
可以看到,服务端并没有结束...需要手动关闭,才能进行在进行下一个测试
3.打开文件夹,输入 ftp://127.0.0.1:8080,服务端输出
get a socket
然后文件夹进入假死状态...强制关闭后输出
Exception in thread "main" java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:168) at java.net.SocketInputStream.read(SocketInputStream.java:182) at t2.Server.main(Server.java:22)
4.打开控制台(cmd),输入telnet 127.0.0.1 8080 ,在输入任意数,发现服务端将会依次显示任意数。。直到关闭控制台
进入telnet后按ctrl+]在按回车,会有输入结果回写哦。。。(看不懂的话试试就知道了,无法用语言形容)
5.打开qq,换上http代理,地址127.0.0.1,端口8080,点下测试玩玩(差不多就关了,就会出现socket is over,反正qq没假死对吧)
get a socket CONNECT tcpconn2.tencent.com:443 HTTP/1.1 Host: tcpconn2.tencent.com:443 Accept: */* Content-Type: text/html Proxy-Connection: Keep-Alive Content-length: 0 socket is over
6.7你所能想到的所有可以发送请求,建立连接的方式,比如mstsc,svn,其他的代理方式。。。
总结一下:
当看到Client链接使用的是Socket而Server获取的也是Socket时,是否会认为他2是同一个对象呢...Client这边的Socket存在我们操作的电脑中,而Server中的Socket则存在为我们提供服务的电脑中(服务器),当然,我们可以通过类似于Socket和ServerSocket的机制,来创建一种消息机制(对他们进行封装),是他们接受的对象都相同
在这个例子里面,因为使用(i=inputStream.read())!=-1判断请求是否中断的具体实现,所以对Client也有了一点的要求,可见前后台的交互必须遵照一定的约定才能够准确的进行通信,即不同的服务器要遵守不同的协议,而WEB服务器遵守的就是http协议(所以也叫HTTP服务器),再次强调链接仅仅与地址和ip相关,不遵守协议服务器只是不提供服务而已
我们是要玩tomcat的男人,那就让serversocket依照http协议来一次,看看效果呗
测试三之前:我们要了解一下http协议
通过前面的测试,可以看到通信见相互传递的就是一些字节流,比如测试二.2中打印
GET / HTTP/1.1 Host: 127.0.0.1:8080 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: JSESSIONID=C8CD6B63C4FC2C05A3CA48D667F4A484 Connection: keep-alive
当然,这是web客户端(浏览器)发送的,肯定遵循HTTP协议,至于其详细内容要查看HTTP协议....好绕口,先不管这些,请求就是它了(反正Socket不用我们写,浏览器都是现成的)
重点是响应是什么....我不否认firebug什么的是可以看到被整理过的请求和响应,但叔要的是最原始的...(好犯贱啊)
我们可以先创建一个JavaWeb项目a,创建一个Servlet->a,然后在cmd中输入127.0.0.1:8080(记得启动tomcat),在输入
GET /a/servlet/a HTTP/1.1
Host:
加两个回车输出
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/html Transfer-Encoding: chunked Date: Wed, 29 Oct 2014 06:08:32 GMT bb <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML> <HEAD><TITLE>A Servlet</TITLE></HEAD> <BODY> This is class a, using the GET method </BODY> </HTML> 0
就是响应流...有点像通过存在的服务器创建服务器一样...但这就是我们的优势
测试三:我们要让server返回能被浏览器识别(遵守Http协议,实在没词了...)
/** * @author 程猿 * 浏览器竟然使用Http1.1协议....这货是个长链接,简单的说,通过(i=inputStream.read())!=-1来判断请求结束是不科学的 * 还好,我发现在telnet中2发回车( , )就可以获取响应,也许这就是他的结束标识 */ public class Server { public static void main(String args[])throws Exception { ServerSocket server = new ServerSocket(8080); while (true) { Socket socket = server.accept(); //接受请求 InputStream inputStream = socket.getInputStream(); int i=0; boolean flag=false;; while((i=inputStream.read())!=-1){ if(i==' '&&flag==true){ break; } if(i==' '){ flag=true; }else{ flag=false; } System.out.print((char)i); } //发送回应 OutputStream outputStream = socket.getOutputStream(); String str = "HTTP/1.1 200 OK " + "Server: Apache-Coyote/1.1 " + "Content-Type: text/html " + "Transfer-Encoding: chunked " + "Date: Wed, 29 Oct 2014 06:08:32 GMT " + " " + "bb " + "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> " + "<HTML> " + " <HEAD><TITLE>A Servlet</TITLE></HEAD> " + " <BODY> " + " This is class a, using the GET method " + " </BODY> " + "</HTML> " + " " ; outputStream.write(str.getBytes()); socket.close(); } } }
这一次只有Server...点击浏览器看看获取到什么...很显然,只要不断地修改HTML里面的内容,我们就能控制浏览器的展示效果(尽管略显2B。。。)
ServerSocket与Socket的简单测试到这里了就结束了,通过JDK_API可以看到这货比想象中的要复杂得多...管他呢,以后遇见再说吧
第一章 一个简单的web服务器
1.服务器或者说互联网究竟是什么,说不清楚,不过其工作形式就是资源的交换,而资源又有两种,1种为静态资源,比如各种视屏,文件,1种为动态资源或者称之为服务...
2.将输入流封装为request,将输出流封装为response
3.serversocket/socket与http协议
以上就是我对第一章内容的总结