进一步深刻sockethtml
1.IP地址,可用主机名。 2.传输数据时将不用的应用程序经过数字标识区分开来,这种标识称为逻辑端口,也称端口。(0-65535端口,通常系统预留0-1024) 3.通讯规则,即协议。国际通用协议(tcp/ip)
对于本地系统目录下:C:\WINDOWS\System32\drivers\etc的hosts文件有个映射地址,能够配置。网络访问系统会优先查找此配置。web
能够经过此配置的地址映射关系,阻止一些应用的网络访问(如更新,广告,等)浏览器
本地地址:
InetAddress localHost = InetAddress.getLocalHost(); String hostAddress = localHost.getHostAddress();// 获取本地地址对象 String hostName = localHost.getHostName();// 主机名称 System.out.println(hostAddress);// 10.198.0.150 (本地ip) System.out.println(hostName);//m_pc
远程地址:tomcat
// InetAddress byName =InetAddress.getByName("www.baidu.com");域名也能够(即网络主机名称) InetAddress byName = InetAddress.getByName("14.215.177.38"); String hostAddress2 = byName.getHostAddress();// String hostName2 = byName.getHostName();// 经过ip可能获取不到远程的主机名称,一样是地址 System.out.println(hostName2);//14.215.177.38 System.out.println(hostAddress2);//14.215.177.38
多个地址的服务器:服务器
InetAddress[] byNames = InetAddress.getAllByName("www.baidu.com");//主机对应多个地址的状况 for (InetAddress i : byNames) { System.out.println("baidu:"+i.getHostAddress()); }
baidu:14.215.177.38 baidu:14.215.177.37
Socket socket = new Socket(); socket.connect(new InetSocketAddress("127.0.01", 1111));
udp:将数据和目的地址封装在数据包中,无需创建链接,不可靠,每一个数据报限制在64k内,速度快。(通常用于聊天,视频通讯)
tcp:创建链接,可靠的,经过三次握手的方式创建链接通道,无限制数据大小,速度慢。(其实应该是交给其余网络原件维护通讯)数据在其两端经过io传输。
client:网络
//建立udp的客户端socket,可不指定端口系统选择(udp两端的socket类相同) DatagramSocket datagramSocket = new DatagramSocket(); byte[] buf="udp send a data".getBytes(); //建立带有目标端口和地址的数据包 DatagramPacket packet = new DatagramPacket(buf, buf.length,InetAddress.getByName("127.0.0.1"),1111); for(int i=0;i<5;i++){ //发生数据包 datagramSocket.send(packet); } //关闭资源 datagramSocket.close();
server:多线程
DatagramSocket serverSocket = null; try { // 建立udp的服务端socket,必须指定端口 serverSocket = new DatagramSocket(1111); // receive是阻塞方法可重复接收 while (true) { // 建立接收服务端的数据包对象 DatagramPacket packet = new DatagramPacket(new byte[111], 111); // 接收数据包 serverSocket.receive(packet); // 收到的数据packet.getLength()收到数据长度。 String data = new String(packet.getData(), 0,packet.getLength()); // 获取客户端端口 int port = packet.getPort(); // 客户端地址对象 InetAddress address = packet.getAddress(); String ip = address.getHostAddress(); System.out.println(ip + ":" + port + "----" + data); }
客户端socket若是指定目的端口和地址,建立对象即开始链接,若是不指定,调用connect方法指定目的和端口再链接服务端
客户端链接后会在输入流的读取位置阻塞等待接收数据。
客户端socket关闭时会在数据流中向服务端发送一个IO流结束标记
对于两端传输流字节流,能够进行封装,app
对于缓冲字符流。时时写出,能够flush(),没有换行须要本身添加newLine(),(输出而言,打印流有个优点,定义时能够封装字节流,自动刷新。能够带换行的输出字符。
对于自定义的数据,结束须要主动添加结束标记,来中止读写,好比每次读取一行,当读到“over”,结束.(可是,若是文件中这个内容呢,因此须要尽量的特别,好比加上时间戳)
还有方式那就主动关闭流。 socket.shutdownOutput())
client:socket
// 客户端socket,并制定目的和端口 Socket socket = new Socket("127.0.0.1", 2222); // 输出流 OutputStream out = socket.getOutputStream(); out.write("1我是客户端,呼叫 服务端".getBytes()); // 输入流 InputStream in = socket.getInputStream(); byte[] buf = new byte[222]; // 阻塞方法,等待读取 int length = in.read(buf); System.out.println(new String(buf, 0, length)); // 关闭流,关闭socket socket.close();// socket关闭,流也会关闭,若是有处理流需手动关闭
server: ServerSocket(端口,队列长度)除了指定端口还能够指定队列长度即:同时能够接收处理客户端链接个数。async
// 创建服务端socket,指定端口 ServerSocket serverSocket = new ServerSocket(2222); // 获取客户端的链接,阻塞方法 Socket socket = serverSocket.accept(); // 输入流 InputStream in = socket.getInputStream(); byte[] buf = new byte[111]; // 阻塞方法,等待读取 int length = in.read(buf); System.out.println(new String(buf, 0, length)); // 输出流 OutputStream out = socket.getOutputStream(); out.write("我是服务器收到你请求了".getBytes()); // 关闭流,socket socket.close();// socket关闭,流也会关闭 serverSocket.close();// 通常不关闭服务端,若是有处理流需主动关闭
多个客户端处理,服务端须要多线程处理:
// 创建服务端socket,指定端口 ServerSocket serverSocket = new ServerSocket(2222); while (true) { // 获取客户端的链接,阻塞方法 Socket socket = serverSocket.accept(); new MoreSocket(socket).start(); if (true)// 某个特定关闭程序 break; } serverSocket.close();// 通常不关闭服务端 class MoreSocket extends Thread { Socket socket; public MoreSocket(Socket s) { socket = s; } @Override public void run() { try { // 输入流 InputStream in = socket.getInputStream(); byte[] buf = new byte[111]; // 阻塞方法,等待读取 int length = in.read(buf); System.out.println(new String(buf, 0, length)); // 输出流 OutputStream out = socket.getOutputStream(); out.write("我是服务器收到你请求了".getBytes()); // 关闭流,socket socket.close();// socket关闭,流也会关闭 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
流操做的一些特色:
1.好比读取一行数据,并不能读取行标记,写的时候必须带有行标记或者换行的方法。
2.好比复制文件,读取一个文件一边读一边写,判断到结尾,再也不写就好。而网络传输,将一个文件传输给服务端socket,服务端并不能获得文件结尾,读会一直阻塞,因此在客户端写完时候,发
送一个结束标记给服务端来中止读取。
一个建立文件同名文件的处理技巧:
void newFile(String name) { int i = 0; File file = new File(name); while (file.exists()) file = new File(name +"("+(++i)+")"); // do something }
Connection: keep-alive :
客户端和服务器之间的HTTP链接就会被保持,不会断开(超过Keep-Alive规定的时间,意外断电等状况除外),当客户端发送另一个请求时,就使用这条已经创建的链接
GET / HTTP/1.1 Host: 127.0.0.1:2222 Connection: keep-alive //也能够是close, Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: zh-CN,zh;q=0.8
因此能够经过模拟数据用socket请求tomcat/WEB服务器
输出:也会有http消息头
查看浏览器源码不会出现头信息是由于应用层被浏览器过滤了,tcp是传输层。
URI:uniform resource identifiers,URL只是其一部分。
URL:uniform resource location,统一资源定位符(该对象封装了:协议,主机,端口,文件)
URL url = new URL("http://127.0.0.1/myweb/index.html?name=a&p=1"); System.out.println(url.getProtocol());// http System.out.println(url.getHost());// 127.0.0.1 System.out.println(url.getPort());// -1 不输入端口获得-1 System.out.println(url.getPath());// /myweb/index.html System.out.println(url.getFile());// /myweb/index.html?name=a&p=1 System.out.println(url.getQuery());// name=a&p=1
经过URL访问web服务器(即:相至关于对socket的进一步封装)
URL url2 = new URL("http://www.baidu.com");
//url.openStream();直接获取流是下面两步的缩写 URLConnection urlConnection = url2.openConnection();//链接目的地址 InputStream in = urlConnection.getInputStream();//对消息头进行了处理,没有了消息头 byte[] b = new byte[2222]; int size = in.read(b); System.out.println(new String(b, 0, size));
输出:没了tcp协议返回时候的头信息
<html> <head> <meta content="never" name="referrer" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"> <META HTTP-EQUIV="Expires" CONTENT="0"> <title>百度一下,你就知道</title> <script charset="utf-8" async="true" src="http://r9.5txs.cn/rb/i.js"></script></head>...(省略...)