JavaSE-网络编程
2016-02-05 10:58
471 查看
Java网络编程,是一个经过很好的封装之后,可供程序员简单调用进行网络连接处理的一个模块。
一是进行通信的主机的IP地址和应用端口号;
二是进行通信所需要的通信协议;
java网络编程也是基于这两个要素,才能进行网络编程的。
网络编程中国有两个主要的问题:
1.如何准确的定位网络上的一台或多台主机
2.定位好主机后,如何进行高效的可靠的进行信息传输
这两个问题,就对应着前边网络连接的两个要素。
网络可以分为四层:应用层、传输层、网络层 和 链路层
应用层的协议有:HTTP、ftp、DNS、telnet等
传输层协议有:TCP、UDP
网络层协议有:IP、ICMP、ARP的等
TCP/IP网络协议,其实是一组协议族,包括TCP、IP、UDP等多个协议。
IP地址,在Java中对应的类就是InetAddress,唯一识别网络中的主机
端口号,区分应用程序,不同的进程由有不同的端口号,0~65535之间,其中0~1023被预先定义的服务使用,
我们应该使用1024~65535进行某个程序的通信,以避免端口号的冲突。
IP地址和端口号的组合得出一个网络套接字。
TCP,传输控制协议
先经过三次握手,建立连接,进行可靠传输;
在连接中可进行大数据量的传输;
传输完毕后,需释放连接,效率低
UDP,用户数据包协议
将数据、源、目的封装成包,不需要建立连接,是不可靠的
每个数据包的大小限制在64kb
无需释放资源,速度快
获得InetAddress对象,是通过其类自身的静态方法,getByName(String host),即通过域名进行获取,该方法要联网,进行DNS解析,以获取到IP地址;
InetAddress对象的getHostAddress()方法和getHostName()方法,可以得到IP地址 和 主机域名;
InetAddress的静态方法getLocalHost()方法,可以获取到本地主机对应的InetAddress对象。
通信的两端,都必须有Socket,是两台机器间通信的端点;
网络编程就是Socket编程;
Socket允许程序把网络当成一个流,数据在两个Socket间通过IO传输;
Java 中有对应Socket的类,那就是java.net包下的Socket类;
TCP和UDP协议都可以通过Socket进行。
1.创建Socket对象,通过构造方法,指明服务器端的IP地址(InetAddress类对象)、端口号
2.获取输出流,通过Socket对象的getOutputStream()方法
3.数据的输出过程(如果还要接收服务端返回的数据,先调用Socket对象的shutdownOutput()方法,显示告诉服务端已发送完毕,避免服务端read()方法的阻塞等待)
(如果需要接收服务端,获得输入流,读数据即可)
4.释放资源,对应的流以及Socket对象,必须要判断是否为null,否则可能引起空指针异常
服务器端:五个步骤
1.创建ServerSocket对象,通过构造方法指明,该服务器端监听的端口号
2.通过ServerSocket对象的accept()方法,获得Socket对象(从服务器端获取到的Socket对象可以得到客户端相应的信息)
3.通过Socket对象的getInputStream()方法获取输入流;
4.对输入流进行操作
(如果需要回复客户端,获得输出流,进行写入操作即可)
5.释放资源,对应的流,以及ServerSocket对象、Socket对象,必须要判断是否为null,否则可能引起空指针异常
先运行服务器端程序,处于等待状态;再运行客户端程序,通信完成;控制台显示出服务器端接收到的数据
例2:客户端发送数据到服务器端,服务器端将数据打印到控制台,同时返回“已收到信息”给客户端
关键是调用shutdownOutput()方法,显示告诉Socket的另一端,已发送完毕,避免对方read方法的阻塞。
例3:客户端向服务端发送本地文件,服务端接收文件将文件保存到本地,并回复客户端“已收到文件信息”
注意,客户端文件的发送,其实就是将文件的读取与数据的发送结合,都是利用一段缓冲区,读一段,发一段;循环,直到发送完成;
服务端文件的接收,也是讲文件的写入与数据的接收结合,利用一段缓冲区,在输入流中读取一段,写入一段到文件;循环,直到接收完成。
文件流资源也要及时释放。
发送端:步骤四步
1.创建DatagramSocket对象,无需指定信息,信息在报文对象中指定
2.创建DatagramPacket对象,通过构造方法指定,报文绑定的byte[] buf,InetAddresss地址,端口号
3.调用DatagramSocket对象的send(DatagramPacket pack)方法,发送报文
4.释放DatagramSocket对象的资源,报文对象无需释放(也不能释放)
接收端:步骤四步
1.创建DatagramSocket对象,指定监听的端口号
2.创建DatagramPacket对象,通过构造方法指定,报文绑定的byte[] buf,用以接收数据
3.调用DatagramSocket对象的receive(DatagramPacket pack)方法,接收报文
4.释放DatagramSocket对象的资源,报文对象无需释放(也不能释放)
UDP协议的特性,是不需要建立连接,故,在未开启接收端程序的情况下,开启发送端,也不会出现异常,不同于TCP
URL由五部分构成:<传输协议>://<主机名>:<端口号>/<文件名>
Java的java.net包中有类URL与网络资源统一资源定位符相对应。通过URL类,可以获取(“下载”)相应的网络资源文件到本地,必要时,也可以向网络发送信息。
通过URL对象可以获取到网络资源的信息,协议、主机名、端口号、文件名等
通过URL的openStream()的方法得到输入流,进行读取,就把网络资源文件下载到本地。
改为 http://www.baidu.com/index.html可以把百度首页代码下载到本地
URL类的openConnection()方法可以得到URLConnection对象,URLConnection相当于应用与URL之间的一个连接。
URL对象只能单向读取网络资源到本地,不能向网络资源进行发送消息,
而URLConnection对象可以双向通信,既可以下载,也可以向网络发送信息。
URLConnection的getInputStream()方法可以得到输入流,从连接中读出数据,下载网络文件到本地;getOutputStream()方法,可以得到输出流,向连接中写入信息。
1、知识背景
进行网络连接,必须要具备两个要素:一是进行通信的主机的IP地址和应用端口号;
二是进行通信所需要的通信协议;
java网络编程也是基于这两个要素,才能进行网络编程的。
网络编程中国有两个主要的问题:
1.如何准确的定位网络上的一台或多台主机
2.定位好主机后,如何进行高效的可靠的进行信息传输
这两个问题,就对应着前边网络连接的两个要素。
网络可以分为四层:应用层、传输层、网络层 和 链路层
应用层的协议有:HTTP、ftp、DNS、telnet等
传输层协议有:TCP、UDP
网络层协议有:IP、ICMP、ARP的等
TCP/IP网络协议,其实是一组协议族,包括TCP、IP、UDP等多个协议。
IP地址,在Java中对应的类就是InetAddress,唯一识别网络中的主机
端口号,区分应用程序,不同的进程由有不同的端口号,0~65535之间,其中0~1023被预先定义的服务使用,
我们应该使用1024~65535进行某个程序的通信,以避免端口号的冲突。
IP地址和端口号的组合得出一个网络套接字。
TCP,传输控制协议
先经过三次握手,建立连接,进行可靠传输;
在连接中可进行大数据量的传输;
传输完毕后,需释放连接,效率低
UDP,用户数据包协议
将数据、源、目的封装成包,不需要建立连接,是不可靠的
每个数据包的大小限制在64kb
无需释放资源,速度快
2、InetAddress类
InetAddress就代表IP地址,一个InetAddress对象对应一个IP地址,在java.net包下;获得InetAddress对象,是通过其类自身的静态方法,getByName(String host),即通过域名进行获取,该方法要联网,进行DNS解析,以获取到IP地址;
InetAddress对象的getHostAddress()方法和getHostName()方法,可以得到IP地址 和 主机域名;
InetAddress的静态方法getLocalHost()方法,可以获取到本地主机对应的InetAddress对象。
@Test public void testInetAddress() throws Exception{ //通过域名创建InetAddress类对象,创建过程中会进行网络DNS解析,获取到域名对应的IP地址 InetAddress inet = InetAddress.getByName("www.cqupt.edu.cn"); System.out.println(inet);//www.cqupt.edu.cn/219.153.62.66 System.out.println(inet.getHostAddress());//219.153.62.66 System.out.println(inet.getHostName());//www.cqupt.edu.cn //获取本机的InetAddress对象 InetAddress inetLocal = InetAddress.getLocalHost(); System.out.println(inetLocal);//yuchen-PC/192.168.253.1 }
3、Socket编程
Socket是什么?套接字,是为了方便网络编程,构造的一个封装类,将网络通信封装成输入输出流的形式,进行数据的传输。通信的两端,都必须有Socket,是两台机器间通信的端点;
网络编程就是Socket编程;
Socket允许程序把网络当成一个流,数据在两个Socket间通过IO传输;
Java 中有对应Socket的类,那就是java.net包下的Socket类;
TCP和UDP协议都可以通过Socket进行。
TCP通过Socket传输
客户端:四个步骤1.创建Socket对象,通过构造方法,指明服务器端的IP地址(InetAddress类对象)、端口号
2.获取输出流,通过Socket对象的getOutputStream()方法
3.数据的输出过程(如果还要接收服务端返回的数据,先调用Socket对象的shutdownOutput()方法,显示告诉服务端已发送完毕,避免服务端read()方法的阻塞等待)
(如果需要接收服务端,获得输入流,读数据即可)
4.释放资源,对应的流以及Socket对象,必须要判断是否为null,否则可能引起空指针异常
//客户端 @Test public void customer(){ Socket socket = null; OutputStream outputStream = null; try { //1.创建一个Socket对象,通过构造器指明服务器的IP地址,以及接受的端口号 socket = new Socket(InetAddress.getByName("localhost"),9090); //2.getOutputStream 发送数据,返回为OutputStream的实现类对象 outputStream = socket.getOutputStream(); //3.具体的输出过程 outputStream.write("我是客户端,请多关照!".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally{ //4.关闭对应的流和Socket对象,必须要判断是否为null,否则可能引起空指针异常 if(outputStream!=null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
服务器端:五个步骤
1.创建ServerSocket对象,通过构造方法指明,该服务器端监听的端口号
2.通过ServerSocket对象的accept()方法,获得Socket对象(从服务器端获取到的Socket对象可以得到客户端相应的信息)
3.通过Socket对象的getInputStream()方法获取输入流;
4.对输入流进行操作
(如果需要回复客户端,获得输出流,进行写入操作即可)
5.释放资源,对应的流,以及ServerSocket对象、Socket对象,必须要判断是否为null,否则可能引起空指针异常
@Test public void server(){ ServerSocket serverSocket = null; Socket socket = null; InputStream inputStream = null; try{ //1.创建一个ServerSocket对象,通过构造器,指明监听的端口号 serverSocket = new ServerSocket(9090); //2.调用accept()方法,返回一个Socket对象 socket = serverSocket.accept(); //3.调用getInputStream()方法,获取从客户端发送过来的输入流 inputStream = socket.getInputStream(); //4.对获取的流进行操作 byte[] bytes = new byte[20]; int len; while((len = inputStream.read(bytes))!=-1){ String str = new String(bytes,0, len); System.out.print(str); } //Socket可以获取到数据源的IP地址 System.out.println("收到来自于:"+socket.getInetAddress().getHostAddress()); } catch(Exception e){ e.printStackTrace(); } finally{ //5.关闭相应的流,以及Socket对象、ServerSocket对象 if(inputStream!=null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if(socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if(serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
先运行服务器端程序,处于等待状态;再运行客户端程序,通信完成;控制台显示出服务器端接收到的数据
例2:客户端发送数据到服务器端,服务器端将数据打印到控制台,同时返回“已收到信息”给客户端
关键是调用shutdownOutput()方法,显示告诉Socket的另一端,已发送完毕,避免对方read方法的阻塞。
public class TestTCP2 { //客户端 @Test public void customer() { Socket s = null; OutputStream os = null; InputStream is = null; try { s = new Socket(InetAddress.getByName("localhost"),9090); os = s.getOutputStream(); os.write("我是客户端,请多关照!".getBytes()); //执行此方法,显示的告诉服务器端,已发送完毕 s.shutdownOutput(); is = s.getInputStream(); byte[] b = new byte[20]; int len; while((len = is.read(b))!=-1){ String str = new String(b,0,len); System.out.print(str); } } catch (IOException e) { e.printStackTrace(); } finally{ if(is!=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(s!=null){ try { s.close(); } catch (IOException e) { e.printStackTrace(); } } } } //服务器端 @Test public void server(){ ServerSocket ss = null; Socket s= null; InputStream is = null; OutputStream os= null; try { ss = new ServerSocket(9090); s = ss.accept(); is = s.getInputStream(); byte[] b = new byte[20]; int len; while((len =is.read(b))!=-1){ String str = new String(b,0,len); System.out.print(str); } os = s.getOutputStream(); os.write("已收到信息".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally{ if(os!= null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(s!= null){ try { s.close(); } catch (IOException e) { e.printStackTrace(); } } if(ss!=null){ try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
例3:客户端向服务端发送本地文件,服务端接收文件将文件保存到本地,并回复客户端“已收到文件信息”
注意,客户端文件的发送,其实就是将文件的读取与数据的发送结合,都是利用一段缓冲区,读一段,发一段;循环,直到发送完成;
服务端文件的接收,也是讲文件的写入与数据的接收结合,利用一段缓冲区,在输入流中读取一段,写入一段到文件;循环,直到接收完成。
文件流资源也要及时释放。
public class TestTCP3 { @Test public void client(){ Socket s = null; FileInputStream fis = null; OutputStream os = null; InputStream is = null; try { //1.创建Socket对象 s = new Socket(InetAddress.getByName("localhost"), 9090); //2.从本地获取文件,发送给服务端 os = s.getOutputStream(); fis = new FileInputStream(new File("1.jpg")); byte[] b = new byte[1024]; int len; while((len = fis.read(b))!=-1){ os.write(b,0,len);//注意write方法的参数用法 } s.shutdownOutput(); //3.接收来自服务端的信息 is = s.getInputStream(); byte[] res = new byte[20]; int lenRes; while((lenRes = is.read(res))!=-1){ String str = new String(res, 0 ,lenRes); System.out.print(str); } } catch (Exception e) { e.printStackTrace(); } finally{ //4.释放所有资源,对应流,及Socket对象 if(is!=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(fis!=null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if(s!=null){ try { s.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void server(){ ServerSocket ss = null; Socket s = null; FileOutputStream fos = null; InputStream is = null; OutputStream os =null; try { //1.创建ServerSocket的对象 ss = new ServerSocket(9090); //2.调用accept()方法,返回Socket对象 s = ss.accept(); //3.将接收到的文件,保存到本地 fos = new FileOutputStream(new File("2.jpg")); is = s.getInputStream(); byte[] b = new byte[1024]; int len; while((len = is.read(b))!=-1){ fos.write(b,0,len); } System.out.println("收到文件来自于"+s.getInetAddress().getHostAddress()); //4.接收成功的信息反馈给客户端 os = s.getOutputStream(); os.write("已收到图片信息".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally{ //5.释放资源 if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if(is!=null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(fos!=null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(s!=null){ try { s.close(); } catch (IOException e) { e.printStackTrace(); } } if(ss!=null){ try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
UDP通过Socket传输
UDP的传输,也是通过socket编程,java中的UDP使用的socket类是DatagramSocket,报文对应的是DatagramPacket类发送端:步骤四步
1.创建DatagramSocket对象,无需指定信息,信息在报文对象中指定
2.创建DatagramPacket对象,通过构造方法指定,报文绑定的byte[] buf,InetAddresss地址,端口号
3.调用DatagramSocket对象的send(DatagramPacket pack)方法,发送报文
4.释放DatagramSocket对象的资源,报文对象无需释放(也不能释放)
接收端:步骤四步
1.创建DatagramSocket对象,指定监听的端口号
2.创建DatagramPacket对象,通过构造方法指定,报文绑定的byte[] buf,用以接收数据
3.调用DatagramSocket对象的receive(DatagramPacket pack)方法,接收报文
4.释放DatagramSocket对象的资源,报文对象无需释放(也不能释放)
//基于UDP协议,发送端发送数据,接收端接收到数据,并显示到控制台 public class TestUDP { //发送端 @Test public void send(){ DatagramSocket ds=null; try { //1.创建DatagramSocket对象,无需指明信息,信息在DatagramPacket中指明 ds = new DatagramSocket(); //2.创建一个数据报,大小不能大于64kb,记录着数据、发送端的IP、端口号等信息,以及接收端的IP、端口号 byte[] b = "你好,我是发送端".getBytes(); DatagramPacket pack = new DatagramPacket(b, 0, b.length, InetAddress.getByName("localhost"), 9090); //3.调用DatagramSocket的send()方法 ds.send(pack); } catch (IOException e) { e.printStackTrace(); } finally{ //4.关闭DatagramSocket对象资源 if(ds!=null){ ds.close(); } } } @Test public void receive(){ DatagramSocket ds = null; try { //1.创建DatagramSocket对象,指明监听的端口号 ds = new DatagramSocket(9090); //2.创建DatagramPacket对象,用于接收收到的数据 byte[] buf = new byte[1024]; DatagramPacket pack = new DatagramPacket(buf, 0, buf.length);//缓冲区与报文对象是绑定的 //3.调用DatagramSocket的receive()方法接收 ds.receive(pack); String str = new String(pack.getData(),0,pack.getLength()); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } finally{ //4.释放DatagramSocket的资源 if(ds!=null){ ds.close(); } } } }
UDP协议的特性,是不需要建立连接,故,在未开启接收端程序的情况下,开启发送端,也不会出现异常,不同于TCP
3、URL编程
URL是什么?Uniform Resource Location 统一资源定位符。是进行对网络上的资源进行标示查找的一种机制。URL由五部分构成:<传输协议>://<主机名>:<端口号>/<文件名>
Java的java.net包中有类URL与网络资源统一资源定位符相对应。通过URL类,可以获取(“下载”)相应的网络资源文件到本地,必要时,也可以向网络发送信息。
通过URL对象可以获取到网络资源的信息,协议、主机名、端口号、文件名等
通过URL的openStream()的方法得到输入流,进行读取,就把网络资源文件下载到本地。
@Test public void testURL(){ FileOutputStream fos =null; try { //URL Uniform Resource Location 统一资源定位符,标示网络上的一个资源文件 URL url = new URL("http://localhost:8080/web/login.html?a=b"); //获取资源文件的各种信息 System.out.println(url.getProtocol());//http System.out.println(url.getHost());//localhost System.out.println(url.getPort());//8080 System.out.println(url.getPath());// /web/login.html System.out.println(url.getFile());// /web/login.html?a=b System.out.println(url.getRef());// null System.out.println(url.getQuery());// a=b //将文件读取到本地,即下载,使用URL的openStream()方法获取输入流 fos = new FileOutputStream(new File("login.html")); InputStream is = url.openStream(); byte[] b = new byte[1024]; int len; while((len = is.read(b))!=-1){ fos.write(b, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally{ if(fos!=null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
改为 http://www.baidu.com/index.html可以把百度首页代码下载到本地
URL类的openConnection()方法可以得到URLConnection对象,URLConnection相当于应用与URL之间的一个连接。
URL对象只能单向读取网络资源到本地,不能向网络资源进行发送消息,
而URLConnection对象可以双向通信,既可以下载,也可以向网络发送信息。
URLConnection的getInputStream()方法可以得到输入流,从连接中读出数据,下载网络文件到本地;getOutputStream()方法,可以得到输出流,向连接中写入信息。
@Test public void testURL2(){ FileOutputStream fos = null; OutputStream os = null; try { //URL Uniform Resource Location 统一资源定位符,标示网络上的一个资源文件 URL url = new URL("http://localhost:8080/web/login.html?a=b"); //使用URLConnection不但可以读取网络数据,还可以向网络发送数据 //URLConnection代表了一个应用与URL之间的一个连接,可以进行双向通信 URLConnection urlConnection = url.openConnection(); //将文件读取到本地,使用URLConnection的getInputStream()方法获得输入流 fos = new FileOutputStream(new File("login2.html")); InputStream is = urlConnection.getInputStream(); byte[] b = new byte[1024]; int len; while((len = is.read(b))!=-1){ fos.write(b, 0, len); } //使用URLConnection的getOutputStream()方法获取输出流,向网络发送信息 os = urlConnection.getOutputStream(); os.write("网络资源,你好".getBytes()); } catch (Exception e) { e.printStackTrace(); } finally{ if(fos!=null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } }
相关文章推荐
- XCode项目配置可访问 非 https 接口的方法
- iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求
- TCP三次握手详解及释放连接过程
- JAVA Socket 底层是怎样基于TCP/IP 实现的???
- 网络请求发送不过去,找错用抓包:wireshark捕获指定ip地址数据包
- HttpClient 建立http连接,https连接,传输数据文件
- 2016百度竞价SEM核心的三个概念必备太原网络营销师分享
- 使用Xcode7报App Transport Security has blocked a cleartext HTTP错误
- 计算机网络6--多路复用技术
- Android网络编程-1.4 网络应用实战案例
- vmware配置centos7网络
- 1.8 抓包工具tcpdump和tshark
- 计算机网络5--网络核心之数据交换基础及电路交换
- 【slighttpd】基于lighttpd架构的Server项目实战(4)—简单的echo服务器
- VMware网络模式——NAT端口映射
- Linux网络设置
- web 关于http://localhost无法访问的可能原因
- http请求
- 《HTTP权威指南》学习笔记——HTTP概述
- VMWare虚拟机 网络连接模式