java网络编程 订阅
《Java网络编程》第三版会为你介绍Java网络API的最新特性。本书讨论了JDK1.4和1.5(现在已命名为J2SE5)中所做的所有修改和增补。本书内容全面,涵盖了从网络基础知识到远程方法调用(RMI)等各方面的内容,书中章节涉及到TCP和UDPsocket、服务器socket、URL和URI、组播以及特殊用途的API(如JavaMail)等等。本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIOAPI编写超高性能的服务器。它还涵盖了Java对网络代理、Webcookie和URL缓存的支持。 展开全文
《Java网络编程》第三版会为你介绍Java网络API的最新特性。本书讨论了JDK1.4和1.5(现在已命名为J2SE5)中所做的所有修改和增补。本书内容全面,涵盖了从网络基础知识到远程方法调用(RMI)等各方面的内容,书中章节涉及到TCP和UDPsocket、服务器socket、URL和URI、组播以及特殊用途的API(如JavaMail)等等。本书展示了如何使用JSSE编写安全的网络应用程序,解释了如何使用NIOAPI编写超高性能的服务器。它还涵盖了Java对网络代理、Webcookie和URL缓存的支持。
信息
页    数
222页
第二版出版社
清华大学出版社
作    者
朱喜福 戴舒樽 王晓勇
定    价
¥24.00元
字    数
365千字
书    名
Java网络编程基础(第2版)
出版时间
2008-10-1
开    本
16
出版社
人民邮电出版社
责任编辑
李凯
ISBN
978-7-115-18503-7
java网络编程内容简介
Java网络编程基础(第2版) [1]  是为Java学习者在了解Java编程的基础知识之后,进一步学习Java网络编程而编写的教材。全书共4章,第1章通过使用MySQL讲述JDBC数据库应用编程,内容紧密围绕“综合实例——Java考试管理系统”来展开;第2章讲述C/S网络编程及应用,通过“综合实例——C/S考试系统”着重讲述C/S模式下的Java网络应用,这个实例与第1章的“Java考试管理系统”相结合,实现了一个完整的实用项目;第3章讲述JSP及JavaBean网站编程,并通过“综合实例——电子商务网站框架”讲述基于Web的电子商务网站的设计与实现;第4章讲述如何应用J2ME开发简单的手机应用程序,并通过一个综合实例完整地讲述了J2ME手机游戏设计与编码实现。 本书内容实用,通俗易懂,循序渐进,实例丰富,并注重培养学生解决实际问题的能力。本书每章都安排了大量有针对性的上机编程练习题,便于教师教学和检验学生的学习效果,帮助学生巩固和加强所学内容。本书可作为高等职业院校、应用型本科院校“Java网络编程”课程的教材;对于具有一定的Java编程基础,并希望进一步熟悉Java网络编程、数据库编程、商务网站开发和手机编程的读者,本书也是一本理想的参考书。
收起全文
精华内容
下载资源
问答
  • Java 网络编程

    万次阅读 多人点赞 2019-05-30 23:07:18
    网络编程 一、网络编程基础概念 首先理清一个概念:网络编程不等于网站编程,网络编程即使用套接字来达到进程间通信,现在一般称为TCP/IP编程。 计算机网络: 把分布在不同地理区域的计算机与专门的外部设备用通信...

    网络编程

    一、网络编程基础概念

    首先理清一个概念:网络编程不等于网站编程,网络编程即使用套接字来达到进程间通信,现在一般称为TCP/IP编程。

    计算机网络:

    把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大,功能强的网络系统,从而使众多的计算机可以方便的互相传递信息,共享硬件,软件,数据信息等资源。

    计算机网络的主要功能:

    1. 资源共享
    2. 信息传输与集中处理
    3. 均衡负荷与分布处理
    4. 综合信息服务(www / 综合业务数字网络 ISDN)

    计算机网络三高问题: 高并发,高性能,高可用。

    计算机网络分类:

    • 局域网
    • 城域网
    • 广域网
    • 互联网
    • 等等…

    (Local Area Network;LAN) 通常我们常见的“LAN”就是指局域网,这是我们最常见、应用最广的一种网络

    二、网络通信协议及接口

    网络通信协议:

    计算机网络中实现通信必须有一些约定,即通信协议;包括对速率,传输代码,代码结构,传输控制步骤,出错控制等制定的标准。

    网络通信接口:

    为了使两个节点之间能进行对话,必须在他们之间建立通信工具(即接口),使彼此之间,能进行信息交换。接口包括两部分:

    • 硬件装置:实现结点之间的信息传送
    • 软件装置:规定双方进行通信的约定协议

    三、通信协议分层思想

    为什么要分层:

    由于结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式就是层次方式,及同层间可以通信,上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。

    通信协议的分层规定:

    把用户应用程序作为最高层,把物理通信线路作为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准。

    四、参考模型

    在这里插入图片描述

    五、IP协议

    在这里插入图片描述

    • 每个人的电脑都有一个独一无二的IP地址,这样互相通信时就不会传错信息了。

    • IP地址是用一个点来分成四段的,在计算机内部IP地址是用四个字节来表示的,一个字节代表一段,每一个字节代表的数最大只能到达255。

    InetAddress类

    说到IP地址,就要引入一个类:InetAddress
    此类表示互联网协议 (IP) 地址。

    InetAddress类无构造方法

    常用方法摘要

    byte[] getAddress()
    返回此 InetAddress 对象的原始 IP 地址。
    static InetAddress getByName(String host)
    在给定主机名的情况下确定主机的 IP 地址。
    String getHostAddress()
    返回 IP 地址字符串(以文本表现形式)。
    String getHostName()
    获取此 IP 地址的主机名。
    static InetAddress getLocalHost()
    返回本地主机。
    127.0.0.1:本机地址,主要用于测试。别名:Localhost

    案例

    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class TestIP {
        public static void main(String[] args) throws UnknownHostException {
            //InetAdress类表示IP地址
    
            //获取本机IP
            InetAddress ip = InetAddress.getLocalHost();
            System.out.println(ip);
            //获得主机名
            System.out.println(ip.getHostName());
            //获得IP地址
            System.out.println(ip.getHostAddress());
        }
    }
    

    案例二

    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class TestIP2 {
        public static void main(String[] args) throws UnknownHostException {
            InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
            // 获取此 IP 地址的主机名。
            System.out.println(inetAddress.getHostName());
            //返回 IP 地址字符串(以文本表现形式)。
            System.out.println(inetAddress.getHostAddress());
        }
    }
    

    运行
    在这里插入图片描述

    六、端口

    • IP地址用来标识一台计算机,但是一台计算机上可能提供多种网络应用程序,如何来区分这些不同的程序呢?这就要用到端口。
    • 端口是虚拟的概念,并不是说在主机上真的有若干个端口。
    • 通过端口,可以在一个主机上运行多个网络应用程序。端口的表示是一个16位的二进制整数,2个字节,对应十进制的0~65535。

    MySQL(3306),Oracle(1521),Tomcat(8080)等等程序都有自己的端口

    查看端口

    • 用命令提示符cmd查看所有端口:netstat -ano
    • 查看具体程序:使用任务管理器查看PID

    InetSocketAddress类

    说到端口,则要引入一个类:InetSocketAddress

    此类实现 IP 套接字地址(IP 地址 + 端口号)。

    构造方法摘要
    InetSocketAddress(InetAddress addr, int port)
    根据 IP 地址和端口号创建套接字地址。
    InetSocketAddress(int port)
    创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值。
    InetSocketAddress(String hostname, int port)
    根据主机名和端口号创建套接字地址。
    常用方法摘要
    InetAddress getAddress()
    获取 InetAddress。
    String getHostName()
    获取 hostname。
    int getPort()
    获取端口号。

    案例

    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    
    public class TestPort {
        public static void main(String[] args) {
            InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",8082);
            System.out.println(inetSocketAddress.getHostName());
            //获得InetSocketAddress的端口
            System.out.println(inetSocketAddress.getPort());
            System.out.println(inetSocketAddress.getHostString());
            //返回一个InetAddress对象(IP对象)
            InetAddress address = inetSocketAddress.getAddress();
        }
    }
    

    七、URL

    URI=URL+URN

    URI:Uniform Resource Identifier ,统一资源标志符。
    URL:Uniform Resource Locator,统一资源定位符。
    URN:Uniform Resource Name,统一资源命名。

    网络三大基石:HTML,HTTP,URL

    URL

    • 在www上,每一信息资源都有统一且唯一的地址,即统一资源定位符。Uniform Resource Locator。
      如:https://localhost:8080/index.html ,有4部分组成。(协议,主机域名或IP,端口号,资源文件名)

    URL类

    构造方法摘要
    URL(String spec)
    根据 String 表示形式创建 URL 对象。
    URL(String protocol, String host, int port, String file)
    根据指定 protocol、host、port 号和 file 创建 URL 对象。
    URL(String protocol, String host, String file)
    根据指定的 protocol 名称、host 名称和 file 名称创建 URL。

    常用方法摘要
    String getAuthority()
    获取此 URL 的授权部分。
    int getDefaultPort()
    获取与此 URL 关联协议的默认端口号。
    String getFile()
    获取此 URL 的文件名。
    String getHost()
    获取此 URL 的主机名(如果适用)。
    String getPath()
    获取此 URL 的路径部分。
    int getPort()
    获取此 URL 的端口号。
    String getUserInfo()
    获取此 URL 的 userInfo 部分。

    案例

    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class TestURL {
        public static void main(String[] args) throws MalformedURLException {
    
            URL url2 = new URL("https://www.bilibili.com/");
            
            //获取此的授权部分 URL 。
            System.out.println(url2.getAuthority());
    
            //获取此 URL的文件名。
            System.out.println(url2.getFile());
    
            //获取端口
            System.out.println(url2.getPort());
    
            //获取主机
            System.out.println(url2.getHost());
    
            //获得默认端口
            System.out.println(url2.getDefaultPort());
    
            //获得路径
            System.out.println(url2.getPath());
    
            //获取该 URL的userInfo部分。
            System.out.println(url2.getUserInfo());
        }
    }
    
    

    小结:

    在这里插入图片描述

    八、TCP协议和UDP协议

    在这里插入图片描述

    • TCP和UDP位于同一层,都是建立在IP层的基础之上。由于两台电脑之间有不同的IP地址,因此两台电脑就可以区分开来,也就可以互相通话了。
    • 通话一般有两种通话方式:第一种是TCP,第二种是UDP。
    • TCP是可靠的连接,TCP就像打电话,需要先打通对方电话,等待对方有回应后才会跟对方继续说话,也就是一定要确认可以发信息以后才会把信息发出去。TCP上传任何东西都是可靠的,只要两台机器上建立起了连接,在本机上发送的数据就一定能传到对方的机器上。
    • UDP就好比发电报,发出去就完事了,对方有没有接收到它都不管,所以UDP是不可靠的。
    • TCP传送数据虽然可靠,但传送得比较慢;UDP传送数据不可靠,但是传送得快。

    UDP编程:

    需求:完成在线咨询功能,学生和老师在线一对一交流
    分析

    • 使用基于UDP协议的Socket网络编程实现
    • 不需要利用IO流实现数据的传输
    • 每个数据发送单元被统一封装成数据包的方式,发送方将数据包发送到网络中,数据包在网络中去寻找他的目的地,一切以包为中心。

    UDP基本概念:

    • DatagramSocket:用于发送或接收数据包的套接字
    • DatagramPacket:数据包

    实现

    接收方

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    public class PeopleOne {
        public static void main(String[] args) throws IOException {
            //1.开放一个端口
            DatagramSocket socket = new DatagramSocket(5051);
            //2.准备容器接收
            byte[] receiveBuf = new byte[100];
            //3.等待包裹容器封包
            DatagramPacket packet = new DatagramPacket(receiveBuf,receiveBuf.length);
            System.out.println("等你包裹来。。。。");
            while (true){
                //4.接收包裹
                socket.receive(packet);
                //5.解析包裹
                String receStr = new String(packet.getData(),0,packet.getLength());
                System.out.println("我收到了:"+receStr);
                if (receStr.equals("exit")){
                    break;
                }
            }
            //6.释放资源
            socket.close();
        }
    }
    

    发送方

    import java.io.IOException;
    import java.net.*;
    import java.util.Scanner;
    
    public class PeopleTwo {
        public static void main(String[] args) throws IOException {
            //1.指定一个端口进行发送
            DatagramSocket socket = new DatagramSocket();
            //2.指定一个IP
            InetAddress addr = InetAddress.getByName("127.0.0.1");
            int port = 5051;
            //3.准备一个小容器
            byte[] sendBuf;
            while (true){
                Scanner scanner = new Scanner(System.in);
                System.out.println("你要发什么东西:");
                String s = scanner.nextLine();
                //4.加入要放的数据
                sendBuf = s.getBytes();
                //5.数据打包
                DatagramPacket packet = new DatagramPacket(sendBuf,sendBuf.length,addr,port);
                //6.发送包
                socket.send(packet);
                if (s.equals("exit")){
                    break;
                }
            }
            //7.释放资源
            socket.close();
        }
    }
    

    运行
    在这里插入图片描述
    在这里插入图片描述

    TCP编程:

    需求:完成网络登录功能

    • 用户输入用户名密码,服务器给出登录成功或失败的提示

    分析

    • 使用基于TCP协议的Socket网络编程实现
    • TCP协议基于请求响应模式
    • 在网络通讯中,第一次主动发起通讯的程序被作为客户端程序
    • 第一次通讯中等待连接的程序被称作服务器程序
    • 利用IO流实现数据的传输

    实现

    服务器

    import java.io.DataInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TestServer {
    
        public static void main(String[] args) throws IOException {
            //服务器开启了一个监听端口
            ServerSocket serverSocket = new ServerSocket(6666);
            System.out.println("开启了服务器");
            while (true){
                //等待客户端连接
                Socket accept = serverSocket.accept();
                System.out.println("有一个人连接过来了");
                //获得客户端输入的东西
                InputStream inputStream = accept.getInputStream();
                //包装成DataInputStream流
                DataInputStream dataInputStream = new DataInputStream(inputStream);
                //通过流流读取消息
                String s = dataInputStream.readUTF();
                System.out.println(s);
            }
        }
    }
    

    客户端

    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    
    public class TestClient {
        public static void main(String[] args) throws IOException {
            //创建同一连接
            Socket s = new Socket("127.0.0.1",6666);
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());
            dos.writeUTF("hello,world!");
        }
    }
    

    运行
    在这里插入图片描述

    九、Socket编程

    一般的网络编程都称为Socket编程,Socket的英文意思是“插座”。

    在这里插入图片描述

    • 两台电脑都安装上一个插座,然后使用一根线的两端插到两台电脑的插座上,这样两台电脑就建立好了连接。这个插座就是Socket。

    • 因为互相之间都能互相通信,我说你是我的Server只是从逻辑意义上来讲,我应该把东西先发到你那里去,然后由你来处理,转发。所以你叫Server。但从技术意义上来讲,只有TCP才会分Server和Client。对于UDP来说,从严格意义上来讲,并没有所谓的Server和Client。TCP的Server的插座就叫ServerSocket,Client的插座就叫Socket。

    • 两台计算机互相连接,那么首先必须得知道它们的IP地址,但是只提供IP地址是不够的,还必须要有连接的端口号,也就是要连接到哪个应用程序上。

    • 端口号是用来区分一台机器上不同的应用程序的。端口号在计算机内部是占2个字节。一台机器上最多有65536个端口号。一个应用程序可以占用多个端口号。端口号如果被一个应用程序占用了,那么其他的应用程序就无法再使用这个端口号了。记住一点,我们编写的程序要占用端口号的话占用1024以上的端口号,1024以下的端口号不要去占用,因为系统有可能会随时征用。端口号本身又分为TCP端口和UDP端口,TCP的8888端口和UDP的8888端口是完全不同的两个端口。TCP端口和UDP端口都有65536个。

    展开全文
  • java网络编程

    千次阅读 2018-05-09 23:14:53
    java网络编程 最近学习了java网络编程,特在此记录,为方便日后查看,也为了广大小伙伴们有个参考(由易到难)。最最重要的概念: 网络编程分为服务端和客户端。服务端就相当于我们平时说的服务器,有固定的IP地址...

    java网络编程

            最近学习了java网络编程,特在此记录,为方便日后查看,也为了广大小伙伴们有个参考(由易到难)。

    最最重要的概念:

            网络编程分为服务端和客户端。服务端就相当于我们平时说的服务器,有固定的IP地址,随时等待服务器连接并做出响应;而客户端相当于各种端系统,找到服务端进行连接获取服务(我们下面的程序也是这样,首先启动服务端等待连接,然后启动客户端连接服务端。如果先启动客户端再启动服务端则会报错)。       

    说到java的网络编程倒不如说是Java的I/O编程,因为整个过程中关于服务端和客户端的socket创建也就那么两三行代码,其余的都是操作字节流,字符流等。

    一、通过socket传输任意字符,将字符转换为大写后传回客户端

    思路:

    服务端

    (1)     创建服务器,指定端口ServerSocket(intport)

    (2)     采用阻塞式接收客户端连接

    (3)     当客户端连接时打印出“一个客户端建立连接字样”

    (4)     建立字节输入流,接收客户端输入

    (5)     建立字节输出流,将客户端输入的字节转换为大写后输出给客户端

    (6)     清空缓存,但是并不关闭流,因为我们想循环接收用户输入,持续反应

    客户端

    (1)     创建客户端指定服务器+端口,此时就在连接

    (2)     创建输入流,从键盘接收数据

    (3)     创建字节输出流,将用户的输入通过socket传输给服务器

    (4)     清空缓存

    (5)     创建字节输入流接收服务器传回的数据,并打印出来

    服务端代码:

    package com.example.netsocket;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.SocketException;
    import java.net.SocketTimeoutException;
    /**
     * 1、//创建服务器,指定端口 ServerSocket(int port)
     * 2、//接收客户端连接,阻塞式
     * 3、发送数据+接受数据
     * @author 竹轩听雨
     *
     */
    public class Server{
    	public static void main(String[] args) throws IOException {
    		//创建服务器,指定端口 ServerSocket(int port)
    		ServerSocket serverSocket = new ServerSocket(16066);
    		//接收客户端连接,阻塞式
    		Socket client = serverSocket.accept();
    		OutputStream out = client.getOutputStream();
    		BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
    		DataInputStream dis = new DataInputStream(client.getInputStream());
    		DataOutputStream dos = new DataOutputStream(out);
    		String inputMsg = "";
    		String outputMsg = "";
    				
    			System.out.println("一个客户端建立连接");
    			//发送数据
    			String msg = "欢迎连接";
    			while(true) {
    			//inputMsg = in.readLine();
    			inputMsg  = dis.readUTF();
    			System.out.println(inputMsg);
    			dos.writeUTF("服务器-->" + inputMsg.toUpperCase());
    			dos.flush();
    		}
    	}
    	
    
    }
    	
    	

    客户端代码:

    package com.example.netsocket;
    
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.Socket;
    import java.net.UnknownHostException;
    /**
     * 1、创建客户端必须指定服务器+端口,此时就在连接
     * 2、接收数据+发送数据
     * @author 竹轩听雨
     *
     */
    public class Client {
    	public static void main(String[] args) throws UnknownHostException, IOException {
    		//创建客户端必须指定服务器+端口,此时就在连接
    		Socket client = new Socket("localhost",16066);
    		String outputMsg = "";
    		String inputMsg = "";
    		//控制台输入
    		BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
    		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    		DataInputStream dis = new DataInputStream(client.getInputStream());
    		
    	
    
    		while(true) {
    			//输出流
    			outputMsg  =console.readLine();
    			if(outputMsg.equals("break")) 
    				break;
    			dos.writeUTF(outputMsg);
    			dos.flush();
    			//输入流
    			inputMsg = dis.readUTF();
    			System.out.println(inputMsg);
    			
    		}
    		
    		//开始传输文件
    		//判断是否读到文件末尾
    //		while((len = fileReader.read(buf)) != -1) {
    //			out.write(buf,0,len);
    //		}
    		
    		//输入流
    //		inputMsg = dis.readUTF();
    //		System.out.println(inputMsg);
    		//告诉服务器,文件已传输完毕
    //		dos.flush();
    //		//获取从服务器返回的信息
    //		inputMsg = dis.readUTF();
    //		System.out.println(inputMsg);
    		
    		
    	}
    
    }

    实验效果:

    客户端连接后服务端显示“一个客户端建立连接字样”


    在客户端输入数据后接收到服务端返回的大写数据


    客户端接收到的输入


    二、通过socket传输文本文件

    思路:因为要传输中文字符,我们就不用循环逐个接收字节了,而是用更简单的字符流。

    服务端

    (1)     创建服务器,指定端口ServerSocket(intport)

    (2)     采用阻塞式接收客户端连接

    (3)     当客户端连接时打印出“一个客户端建立连接字样”

    (4)     建立字符输入流,接收客户端输入

    (5)     关闭输入流

    (6)     将接收到的数据输出到控制台

    (7)     建立字符输出流,将客户端输入的字符存储到E盘根目录下copy.txt文件(如果此文件不存在则会创建一个新的空白文件,如果存在则会覆盖其中的内容。当然也可以选择追加内容到里面)

    (8)     关闭输出流

    客户端

    (1)     创建客户端指定服务器+端口,此时就在连接

    (2)     创建字符输入流,从F盘根目录下test.txt文本文件中读取数据

    (3)     关闭输入流

    (4)     创建字符输出流,读取的字符通过socket传输给服务器

    (5)     关闭输出流

    (注:请在F盘根目录下放置一个test.txt文件)

    服务端代码:

    package com.example.filetranslation;
    
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.Reader;
    import java.io.Writer;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class FileServer {
    	public static void main(String[] args) throws IOException {
    				
    		//创建服务器,指定端口 ServerSocket(int port)
    		ServerSocket serverSocket = new ServerSocket(16066);	
    		//接收客户端连接,阻塞式
    		Socket client = serverSocket.accept();
    		
    		InputStream in = client.getInputStream();
    		Reader reader = new InputStreamReader(in);
    		char[] data = new char[1024];
    		int len = 0;
    		File file = new File("E:" + File.separator + "copy.txt");
    		Writer writer = new FileWriter(file);
    		
    		System.out.println("一个客户端建立连接");
    		
    		len = reader.read(data);	
    		reader.close();
    		System.out.println(new String(data,0,len));
    
    		if(!"".equals(data)) {
    			writer.write(data);
    			writer.close();
    		}
    	
    	}
    }

    客户端代码

    package com.example.filetranslation;
    
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.Reader;
    import java.io.Writer;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class FileClient {
    	
    	public static void main(String[] args) throws IOException, IOException {
    		//创建客户端必须指定服务器+端口,此时就在连接
    		Socket client = new Socket("localhost",16066);
    		
    		File file = new File("F:" + File.separator + "test.txt");
    		int len = 0;
    		char[] data = new char[1024];
    		
    		OutputStream out = client.getOutputStream();
    		Writer writer = new OutputStreamWriter(out);
    		
    		if(file.exists()) {
    			Reader reader;
    			try {
    				reader = new FileReader(file);
    				len = reader.read(data);
    				reader.close();
    			} catch (FileNotFoundException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		
    			//System.out.println(new String(data,0,len));
    		}
    		
    		if(!"".equals(data)) {
    			writer.write(data);
    			writer.close();
    		}
    
    	
    	}
    
    }

    效果

    F盘根目录下test.txt中的内容

    控制台输出此内容且E盘根目录下出现test.txt文件


    三、传输任意格式文件

    思路:(注意:须在F盘根目录下放置一个test.mp3文件)

    服务端

    (1)     创建服务器,指定端口ServerSocket(intport)

    (2)     采用阻塞式接收客户端连接

    (3)     当客户端连接时打印出“一个客户端建立连接字样”

    (4)     建立字符输入流,接收客户端输入

    (5)     从输入流中循环读取字节数据

    (6)     建立输出流,将从输入流中读取的字节流输出到E盘根目录中

    (7)     输入新缓冲区

    (8)建立字符输出流,给客户端返回“文件上传成功”字样

    (8)     关闭输出流,输出流,socket等

    客户端

    (1)创建客户端指定服务器+端口,此时就在连接

    (2)     输入流,从F盘根目录下test.mp3中循环读取数据并将数据发送给服务端

    (3)     告诉服务端文件已传输完毕

    (4)     获取从服务端反馈的信息(文件上传成功或无信息)

    (5)     将从服务端获得的反馈信息打印到控制台中

    (6)     关闭输入流,输出流,socket等

    服务端代码:

    package com.example.kindsoffile;
    
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.Reader;
    import java.io.Writer;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class FileServer {
    	public static void main(String[] args) throws IOException {
    		
    		//创建服务器,指定端口 ServerSocket(int port)
    		ServerSocket serverSocket = new ServerSocket(16066);	
    		//接收客户端连接,阻塞式
    		Socket client = serverSocket.accept();
    		
    		InputStream in = client.getInputStream();
    		OutputStream out = new FileOutputStream("E:" + File.separator + "test.mp3");
    	
    		byte[] data = new byte[1024];
    		int len = 0;
    		while((len = in.read(data)) != -1) {
    			out.write(data,0,len);
    			out.flush();
    		}
    		
    		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
    		bw.write("文件上传成功");
    		bw.flush();
    		
    		serverSocket.close();
    		client.close();
    		out.close();
    	}
    }

    客户端代码:

    package com.example.kindsoffile;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.Reader;
    import java.io.Writer;
    import java.net.Socket;
    
    public class FileClient {
    	public static void main(String[] args) throws IOException, IOException {
    		//创建客户端必须指定服务器+端口,此时就在连接
    		Socket client = new Socket("localhost",16066);
    		
    		OutputStream out = client.getOutputStream();
    		InputStream in = new FileInputStream("F:" + File.separator + "test.mp3");
    		
    		int len = 0;
    		byte[] data = new byte[1024];
    		
    		while((len = in.read(data)) != -1) {
    			out.write(data,0,len);
    		}
    		//告诉服务器文件已传输完毕
    		client.shutdownOutput();
    		//获取从服务端反馈的信息
    		BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
    
    		System.out.println(br.readLine());
    		//关闭资源
    		client.close();
    		in.close();
    	
    
    	
    	}
    }
    

    效果

    客户端显示服务端传回的“文件上传成功字样”并且在E盘根目录找到test.mp3文件





    展开全文
  • Java网络编程

    千次阅读 2018-10-24 17:54:18
    **Java网络编程** **网络技术基础** OSI模型 我们已经知道,计算机网络是处于不同地理位置的计算机系统通过通信设备和线路连接起来,以网络软件实现资源共享的系统。在计算机网络出现的早期,不同的软件、硬件...
                                        **Java网络编程**
        
                        **网络技术基础**
    	OSI模型
    我们已经知道,计算机网络是处于不同地理位置的计算机系统通过通信设备和线路连接起来,以网络软件实现资源共享的系统。在计算机网络出现的早期,不同的软件、硬件厂商按照各自的标准生产网络软、硬件产品,这就导致了不同厂商、不同结构的网络产品之间互连时会遇到的不兼容性问题。为解决此类问题,国际标准化组织ISO提出了一个OSI(Open System Interconnection,开放系统互联)参考模型,为异构系统互联提供了概念性的框架。
    OSI参考模型采用分层结构,将网络分为七层,如图所示。
    

    在这里插入图片描述

    在这个七层模型中,每一层使用下层提供的服务,同时为上层提供服务。各层的作用分别如下:
    	 物理层。传输信息离不开物理介质,如双绞线和同轴电缆。物理层的任务就是为它的上一层提供物理连接,以及规定通行节点之间的机械和电器等特征。在这一层,数据作为原始的比特流(bit)传输。典型的设备包括集线器(Hub)。
    	 数据链路层。数据链路层负责两个相邻的节点间的线路上,无差错的传送以帧(Frame)为单位的数据。每一帧包括一定量的数据和一些必要的控制信息。在传送数据时,如果接收方检测到所传的数据中有差错,就要通知发送方重新发送这一帧。本层的典型的设备是Switch(交换机)。
    	 网络层。在计算机网络中两台计算机之间可能会经过很多的数据链路,也可能通过很多的通信子网。网络层的任务就是选择合适的网间路由和交换节点,确保数据及时传送到目标主机。在这一层,数据的单位称为包(Packet)。网络层将数据链路层提供的帧组成数据包,包中封装了网络层的包头,包头中含有逻辑地址信息(源主机和目标主机的网络地址)。本层的典型的设备就是路由器(Router)。
    	 传输层。该层的任务是通过通信子网的特性最好地利用网络资源,为两个源主机和目标主机的会话层提供建立、维护和取消传输的连接的功能,以可靠的方式或不可靠的方式。在这一层,以可靠方式传输的数据单位称为段(Segment),以不可靠方式传输的数据单位称为数据报(Datagram)。
    	会话层。在会话层及以上层次中,数据传送的单位不再另外命名,统称为报文(Message)。会话层管理进程之间的会话过程,即负责建立、管理和终止进程之间的会话。会话层还通过数据中插入校验点来实现数据的同步。
    	表示层。表示层对上层的数据进行转换,以保证一个主机的应用层的数据可以被另一个主机的应用层理解。表示层的数据转换包括对数据的加密、解密、压缩、解压和格式转换等。
    	应用层。应用层确定进程之间通信的实际用途,以满足用户的实际请求。例如浏览Web站点、收发E-mail、上传或下载文件等。
    在数据通信中,发送方每一层都将上层的数据加上一个报头,并交给下一层。这一过程重复进行,直到底层的物理层,然后通过物理链路实际传送到接收放。在接收方,则将报头层层剥离,最后将数据交给接收进程。
    不同主机之间的相同层次称为对等层。例如主机A中的表示层和主机B中的表示层互为对等层、主机A中的会话层和主机B中的会话层互为对等层等。对等层之间互相通信需要遵守一定的规则,如通信的内容、通信的方式,我们将其称为协议(Protocol)。我们将某个主机上运行的某种协议的集合称为协议栈。主机正是利用这个协议栈来接收和发送数据的。
    OSI参考模型通过将协议栈划分为不同的层次,可以简化问题的分析、处理过程以及网络系统设计的复杂性。
    
               	TCP/IP分层模型
    ISO制定的OSI参考模型的过于庞大、复杂招致了许多批评。与此对照,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用。实际上,TCP/IP协议也是目前因特网范围内运行的唯一一种协议。图表示了TCP/IP分层模型与OSI模型的对比图。 
    

    在这里插入图片描述

    TCP/IP协议被组织成四个概念层,其中有三层对应于ISO参考模型中的相应层。TCP/IP协议族并不包含物理层和数据链路层,因此它不能独立完成整个计算机网络系统的功能,必须与许多其他的协议协同工作。 
    TCP/IP分层模型的四个协议层分别完成以下的功能: 
    	网络接口层。网络接口层包括用于协作IP数据在已有网络介质上传输的协议。实际上TCP/IP标准并不定义与ISO数据链路层和物理层相对应的功能。相反,它定义像ARP(Address Resolution Protocol,地址解析协议)这样的协议,提供TCP/IP协议的数据结构和实际物理硬件之间的接口。 
    	网络互联层。网络互联层对应于OSI七层参考模型的网络层。本层包含IP协议、RIP协议(Routing Information Protocol,路由信息协议),负责数据的包装、寻址和路由。同时还包含网间控制报文协议(Internet Control Message Protocol,ICMP)用来提供网络诊断信息。 
    	传输层。传输层对应于OSI七层参考模型的传输层,它提供两种端到端的通信服务。其中TCP协议(Transmission Control Protocol)提供可靠的数据流运输服务,UDP协议(User Datagram Protocol)提供不可靠的用户数据报服务。 
    	应用层。应用层对应于OSI七层参考模型的应用层和表示层。因特网的应用层协议包括Finger、Whois、FTP(文件传输协议)、 Gopher、HTTP (超文本传输协议)、Telent(远程终端协议)、SMTP(简单邮件传送协议)、IRC(因特网中继会话)、NNTP(网络新闻传输协议)等。
    网络编程的实质就是编写程序直接或间接地通过网络协议与其它计算机上的某个程序进行通讯。那么,程序员在网络编程中需要关注的问题包括两个:一是如何找到网络上的主机上的要进行通讯的程序,二是找到了主机上的程序后如何传输数据。
    我们首先来看如何找到网络上某个主机上要进行通讯的程序。
    寄信的时候,要在表格中填上邮政服务能够理解的收信人的地址。在给别人打电话之前,必须给电话系统提供联系人的电话号码。同样,一个程序要与另一个程序通信,就要给网络提供足够的信息,使其能够找到另一个程序。在TCP/IP协议中,网络互联层主要负责网络主机的寻址定位。由IP地址就可以唯一确定网络上的一台计算机。因此,我们在程序中只要提供了要通讯的主机的IP地址,就可以找到该主机。除了在程序中提供要寻找的主机的IP地址外,我们还可以提供要寻找的主机的域名,然后互联网上的DNS(域名系统)服务器会自动将该域名转化为IP地址。
    一台主机上可能会运行很多程序,那么我们如何找到该主机上我们要进行通讯的程序呢?TCP/IP协议为了区分主机上的程序,提供了端口(Port)的概念,给每个基于TCP/IP协议运行的网络程序分配一个唯一的端口号。这样,我们只要提供了IP地址和端口号,就可以找到网络上指定主机上要进行通讯的指定程序。
    那么什么是端口号呢?打个比方,邮政服务通过街道地址把信分发到一个邮箱,再由清空邮箱的人把这封信递送到这栋楼的正确房间中。或者考虑一个公司的内部电话系统:要与这个公司中的某个人通话,首先要拨打该公司的总机电话号码连接到其内部电话系统,然后再拨打你要找的那个人的分机号码。于是,IP地址就相当于于街道地址或公司的总机电话号码,端口号就相当于房间号或分机号码。端口号是一组16位的无符号二进制数,每个端口号的范围是1到65535(0被保留)。在互联网上,一些常用的端口号被约定赋给了某些应用程序。例如,端口号21被FTP(File Transfer Protocol,文件传输协议)使用。当你运行FTP客户端应用程序时,它将默认通过这个端口号连接服务器。
    现在,我们已经解决了网络主机上程序的寻址定位问题。下一个问题就是如何传输数据到网络上某个主机的程序中。
    前面我们已经知道,数据传输由TCP/IP分层模型中的传输层负责,该层包含TCP和UDP两种协议。其中,TCP代表传输控制协议(Transfer Control Protocol),它允许两个应用程序之间的进行可靠的通讯。UDP代表用户报文协议(User Datagram Protocol),它是一种非连接协议,允许两个应用程序之间进行不可靠的通讯。
    下面,我们来比较两种协议。
    TCP协议通常可以与打电话相比。如果我们想要给某人打电话,那么他要有一个电话、一个电话号码,并需要等待打进的电话。在我们要呼叫的人应答电话后,我们就有了一个可靠的、双向的通讯流,允许两人相互交流,甚至是同时相互交流。如果其中一人挂掉电话,那么通讯就结束了。
    对于TCP网络连接来说,客户端计算机与打电话的人类似,而服务器计算机与等待接听电话的人类似。当客户端试图连接到服务器时,服务器需要正在运行,需要在网络上有一个地址,需要在一个端口(Port)上等待要来的连接。当TCP连接建立时,客户端和服务器就有了一个可靠的、可以让数据双向传输的双向通讯流。两台计算机可以保持通讯,一直到连接关闭或失败。
    UDP提供了在应用程序之间发送称为数据报的协议。如果把TCP协议比作打电话,那么UDP协议可以比作寄信。报文包如同一封信,客户端发送报文到服务器时,不需要实际连接到服务器。这样,与客户端和服务器直接相连的TCP协议相比,UDP就显得不太可靠。比如,如果在同一天寄两封信,这两封信可能在同一天发出去,也可能这两封信根本就没有发出去。数据报包与此类似。UDP不能确保包会按照它们被发送的顺序接受,也不能保证包肯定会被发出去。
    如果这种不可靠性对于我们编写的程序来说是不可接受的,那就应该使用TCP协议。但是,如果我们开发的网络程序对通讯可靠性没有要求,UDP可能就是一个更好的选择。因为TCP传输中,为确认传送到正确终点没有错误的附加在网络留言后的信息。
    
            客户端和服务器
    在前面的邮政和电话系统例子中,每次通信都是由发信方或打电话者发起,而另一方则通过发回反馈信或接听电话来对通信的发起者作出响应。互联网通信也与这个过程类似。客户端(client)和服务器(server)这两个术语代表了两种角色:客户端是通信的发起者,而服务器程序则被动等待客户端发起通 信,并对其作出响应。客户端与服务器组成了应用程序。客户端和服务器这两个术语对典型的情况作出了描述,服务器具有一定的特殊能力,如提供数据库服务,并使任何客户端能够与之通信。
    一个程序是作为客户端还是服务器,决定了它在与其对等端(Peer)建立通信时使用的套接字API的形式(客户端的对等端是服务器,反之亦然)。更进一步来说,客户端与服务器端的区别非常重要,因为客户端首先需要知道服务器的地址和端口号,反之则不需要。如果有必要,服务器可以使用套接字API,从收到的第一个客户端通信消息中获取其地址信息。这与打电话非常相似:被呼叫者不需要知道拨电话者的电话号码。就像打电话一样,只要通信连接建立成功,服务器和客户端之间就没有区别了。
    
             套接字
    为了能够方便开发网络应用程序,Unix系统推出了一种应用程序访问通信协议的操作系统调用——Socket套接字,使得程序员很方便的访问TCP/IP协议,从而开发各种网络应用程序。后来Windows也引入Socket,Java语言也引入了套接字的编程模型。
    Socket(套接字)是一种抽象层,应用程序通过它来发送和接收数据。一个Socket允许应用程序添加到网络中,并与处于同一个网络中的其他应用程序进行通信。一台计算机上的应用程序向Socket写入的信息能够被另一台计算机上的另一个应用程序读取,反之亦然。
    不同类型的Socket与不同类型的底层协议族以及同一协议族中的不同协议栈相关联。现在TCP/IP协议族中的主要socket类型为流套接字(Stream Socket)和数据报套接字(Datagram Socket)。流套接字将TCP作为其端对端协议,提供了一个可信赖的字节流服务。一个TCP/IP流套接字代表了TCP连接的一端。数据报套接字使用UDP协议,提供了一个“尽力而为”的数据报服务,应用程序可以通过它发送最长65500字节的信息。一个TCP/IP 套接字由一个IP地址、一个端对端协议(TCP或UDP协议)以及一个端口号唯一确定。
    
           	Java对网络编程的支持
    JDK预定义的网络编程相关类均存放在java.net包中。图是Java网络编程中常用类和接口的层次关系图。
    

    在这里插入图片描述

    使用其中的哪些类取决于程序所需处理的通讯协议。例如,基于TCP的应用程序可使用 Socket、ServerSocket 等类;基于UDP的应用程序则使用DatagramPacket、DatagramSocket、MulticastSocket 等类;基于 HTTP 和 FTP 等协议直接访问 URL 资源的应用程序可使用 URL、URLConnection 等类。
    InetAddress类代表IP地址。该类没有构造器,但是提供多个方法: 
    	getByName(String host):根据主机获取对应的InetAddress对象。该方法是静态方法。
    	getByAddress(byte[] address):根据原始IP地址获取对应的InetAddress对象。该方法是静态方法。
    	String getCanonicalHostName():获取此IP地址的全限定域名。
    	String getHostAddress():返回此IP地址对应的IP地址字符串。
    	String getHostName():返回此IP地址对应的主机名。
    	String getLocalHost():获取本地IP地址对应的InetAddress对象。
    URLEncoder和URLDecoder类是HTML格式编码和解码的实用工具类。URLEncoder中提供了一个静态方法encode(String s, string enc),使用指定的编码机制将字符串转换为 application/x-www-form-urlencoded MIME格式。而URLDecoder类提供了一个静态方法 decode(String s, String enc), 使用指定的编码机制对 application/x-www-form-urlencoded 字符串解码。
    
             **TCP套接字编程**
    如果把TCP打比方问打电话,那么套接字(Socket)就是电话。套接字提供了在两台计算机之间使用TCP进行通讯的机制。客户端程序在其通讯的末尾创建一个套接字,并试图将该套接字连接到服务器。当连接建立时,服务器在其通讯末尾建立一个套接字对象。客户端和服务器就可以从套接字中读写来进行通讯。
    java.net包包含了提供所有低层通讯的类。例如,java.net.Socket类代表一个套接字,java.net.ServerSocket类提供了服务器程序监听客户端,并在二者之间建立连接的一种机制。
    当使用套接字在两台计算机之间建立TCP连接时,发生了如图18.4所示的如下步骤:
    1. 服务器初始化一个ServerSocket对象,指示通讯将要发生在哪个端口号上。
    2. 服务器调用ServerSocket类的accept()方法。该方法会一直等待,直到一个客户端连接到服务器上的指定端口。
    3.在服务器等待的同时,客户端实例化一个Socket对象,指定要连接的服务器名和端口号。
    3. Socket类的构造器试图将客户端连接到指定的服务器和端口号。如果通讯建立了,客户端现在就有一个能够与服务器进行通讯的Socket对象。
    4. 在服务器端,accept()方法返回一个将要连接到客户端套接字的服务器新套接字的引用。
    

    在这里插入图片描述

    注意:当客户端建立一个到服务器的套接字连接时,客户端需要指定一个端口号。该端口号指示服务器正在监听的端口。但是,在客户端和服务器使用套接字连接后,它们的连接实际上发生在不同的端口。这就允许在分离线程上的服务器继续在其端口上监听其它客户端。这一切都是在后台发生的,不影响我们的代码。
    在连接建立后,通讯可以通过使用I/O流发生。每个套接字都有一个OutputStream和一个InputStream。客户端的OutputStream连接到服务器的InputStream,同时客户端的InputStream连接到服务器的OutputStream。TCP是一个双向的通讯协议,所以数据可以同时通过两个流发生。
    套接字流是低级I/O流InputStream和OutputStream。因此,它们可以与缓冲流、过滤流以及其它高级流链接在一起,从而可以执行任何类型的高级I/O。这也是为什么我们要在网络编程之前学习java.io包的原因。我们将会发现建立连接是很简单的,网络编程的大部分工作是将数据传过来传过去。当然,这是网络编程应该做的,从而让我们将注意力放在要解决的问题上,而不用关心低层通讯以及协议详细。这也是为什么Java在网络编程中如此流行的原因之一。
    下面,我们来看一个使用套接字的示例。我们将从一个运行在服务器上的程序开始,让它为客户端请求监听某个端口。然后我们再展示如何编写一个连接到服务器应用的客户端代码。
    
                 ServerSocket类
    java.net.ServerSocket类用于服务器程序获得一个端口,并监听客户端请求。该类有四个构造器:
    	public ServerSocket(int port) throws IOException. 创建绑定到特定端口的服务器套接字。如果该端口已经被其它应用程序绑定,那么就会发生一个异常。如果端口号设置为0,将会在任何空闲的端口上创建套接字。
    	public ServerSocket(int port, int backlog) throws IOException.:利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。backlog参数指定可以有多少客户端存在等待队列中。如果队列满了,当客户端试图连接到该端口时,就会接收到一个异常。如果该值为0,就使用本地平台默认的队列大小。
    	public ServerSocket(int port, int backlog, InetAddress address) throws IOException:与上一个构造器相似,但是用InetAddress参数指定要绑定到的本地IP地址。有多个IP地址的服务器可以用InetAddress来指定用哪个IP地址来接收客户端请求。
    	public ServerSocket() throws IOException:创建非绑定服务器套接字。在使用该构造器时,用bind()方法来只绑定服务器套接字。
    如果发生了错误,那么上述每个构造器都会抛出一个IOException异常。如果ServerSocket构造器没有抛出异常,这就意味着程序已经成功绑定到指定端口,并且为客户端请求做好了准备。ServerSocket类的常用方法如下:
    	public int getLocalPort():返回服务器套接字监听的端口。如果我们给ServerSocket的构造器传入端口号为0,让服务器选择一个端口,那么就要用到这个方法。
    	public Socket accept() throws IOException:等待要连接的客户端。该方法会阻塞,直到一个客户端连接到指定端口上的服务器,或者假如我们用setSoTimeout()方法设置了超时值,而套接字超过该值了。否则,该方法就无限阻塞下去。
    	public void setSoTimeout(int timeout):设置超时值,指定在accept()方法调用期间,服务器套接字等待客户端的时间。
    	public void bind(SocketAddress host, int backlog):将套接字绑定到SocketAddress对象中指定的服务器和端口。如果我们使用无参数的构造器实例化一个ServerSocket对象,就要使用该方法。
    以上几个方法中,accept()方法是我们要关注的重点,因为这是服务器如何监听到来的请求的方法。当ServerSocket调用accept()方法时,如果没有设定超时值,该方法就一直要等到客户端连接后才返回。在客户端连接上来以后,ServerSocket就在一个非指定的端口上(这个端口与它监听的端口不同)创建一个新的Socket,并返回一个对这个新Socket的引用。现在TCP连接就在客户端和服务器之间存在了,通讯就开始了。
    注意:如果编写一个允许多个客户端的服务器程序,那么我们肯定想让服务器套接字持续调用accept()来等待客户端。标准的技巧是当客户端连接时,启动一个新线程,用于与新客户端通讯,而让当前线程马上再次调用accept()方法。例如,如果有50个客户端连接到一个服务器,那么服务器端就会有51个线程:50个用于与客户端通讯,1个用于通过accept()方法等待新的客户端。
    
                      Socket类
    java.net.Socket类代表用于客户端和服务器相互通讯的套接字。客户端通过实例化一个Socket获得Socket对象,而服务器从ServerSocket对象的accept()方法的返回值中获得一个Socket对象。Socket类有五个构造器用于将客户端连接到服务器:
    	public Socket(String host, int port) throws UnknownHostException, IOException:试图连接到服务器上指定端口。如果该构造器没有抛出一个异常,那么连接就成功了,而客户端就连接到服务器了。当连接到服务器时,这是最简单的构造器。
    	public Socket(InetAddress host, int port) throws IOException:与上一个构造器相同,但是主机是通过InetAddress对象描述的。
    	public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException:连接到指定的主机和端口,并在本地主机上的指定地址和端口上创建一个套接字。当客户端有多个IP地址,或者想让套接字绑定到特定的本地端口上时,通常使用该构造器。
    	public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException:与前一个构造器相同,但是主机是用InetAddress描述的。
    	public Socket():创建一个非连接的套接字。以后可以使用connect()方法将该套接字连接到服务器。
    当Socket类的构造器返回时,它不仅仅是实例化一个Socket对象。在构造器中,它实际上试图连接到指定的服务器和端口。如果构造器成功返回,客户端就有了一个到服务器的TCP连接。
    下面列出了Socket类的一些方法。注意,因为客户端和服务器都有一个Socket对象,所以客户端和服务器都可以调用这些方法。
    	public void connect(SocketAddress host, int timeout) throws IOException:将套接字连接到指定主机。本方法只有在使用无参数构造器实例化Socket时才需要。
    	public InetAddress getInetAddress():返回该Socket连接到的其它计算机的地址。
    	public int getPort():返回套接字绑定到的远程机器上的端口。
    	public int getLocalPort().:返回套接字绑定到的本地机器上的端口。
    	public SocketAddress getRemoteSocketAddress():返回远程套接字的地址。
    	public InputStream getInputStream() throws IOException:返回套接字的输入流。该输入流连接到远程套接字的输出流。
    	public OutputStream getOutputStream() throws IOException:返回套接字的输出流。该输出流连接到远程套接字的输入流。
    	public void close() throws IOException:关闭套接字,让该Socket对象不再有能力再次连接到任何服务器。
    Socket类包含了很多方法,完整的方法列表请参考JDK文档。我们会注意到Socket类中的很多方法包含允许访问和修改一个连接的不同TCP属性,例如超时值或保持活动状态设置。在所有的Socket类的方法中,最重要的两个方法是getInputStream()和getOutputStream()。下面我们将进行详细讨论。
    
                       **UDP套接字编程**
    用户报文协议(UDP)是用于将二进制数据从一台计算机发送到另一台计算的非连接协议。这里,数据被称为数据报包,它包含了数据将要发送到的目标服务器和端口号。消息的发送者使用数据报套接字发送包,接受者使用数据报套接字接收消息。
    当消息被发送时,接受者并不需要是可用的。同样,当消息接收时,发送者也不需要是可用的。
    
                DatagramSocket类
    数据报包的发送者和接收者都使用java.net.DatagramSocket类分别发送和接收包。DatagramSocket类有四个构造器:
    	public DatagramSocket(int port) throws SocketException:创建数据报套接字,并将其绑定到本地主机指定的端口上。
    	public DatagramSocket(int port, InetAddress address) throws SocketException:使用指定的端口和本地地址创建数据报套接字。如果计算机有多个地址,就应该使用本构造器。
    	public DatagramSocket(SocketAddress address) throws SocketException:在指定的SocketAddress上创建数据报套接字。SocketAddress封装了服务器名和端口号。
    	public DatagramSocket() throws SocketException:创建一个非绑定的数据报套接字。创建之后,可以使用DatagramSocket类的bind()方法将该套接字绑定到一个端口。
    如下是DatagramSocket类的一些方法:
    	public void send(DatagramPacket packet) throws IOException.:发送指定的数据报包。DatagramPacket对象包含了包的目的地信息。
    	public void receive(DatagramPacket packet) throws IOException:接受一个数据报包,将其存在指定的参数上。该方法会一直阻塞,不返回,除非接收到数据报包,或者套接字超时。如果套接字超时,就抛出一个SocketTimeoutException异常。
    	public void setSoTimeout(int timeout) throws SocketTimeoutException.:设置套接字的超时值。这个超时值决定了receive()方法阻塞的微秒数。
    
                   	DatagramPacket类
    DatagramSocket类的send()和receive()方法都带有一个DatagramPacket参数。DatagramPacket类代表一个数据报包,与DatagramSocket类似,包的发送者和接受者都要使用它。DatagramPacket有六个构造器。其中,两个是用于接受者,四个用于发送者。
    如下的两个DatagramPacket构造器用于接收数据报包:
    	public DatagramPacket(byte [] buffer, int length):创建一个数据报包,用于接收指定大小的包。buffer包含了要接收的包。
    	public DatagramPacket(byte [] buffer, int offset, int length):与上一个构造器相同,除了要接收的包的数据存在用offset参数指定的字节数字位置上。
    传递给这些构造器的字节数组用于存储要接收的包的数据,通常是空数组。如果它们不会空,那么要接收的数据报包将覆盖数组中的数据。
    如下的四个构造器用于发送一个数据报包:
    	public DatagramPacket(byte [] buffer, int length, InetAddress address, int port):创建一个数据报包,用于发送指定大小的包。buffer用于存储包数据,address和port描述接收者。
    	public DatagramPacket(byte [] buffer, int length, SocketAddress address):与上一个构造器相似,但是接收者的名字和端口号存储在SocketAddress参数中。
    	public DatagramPacket(byte [] buffer, int offset, int length, InetAddress address, int port):创建一个数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
    	public DatagramPacket(byte [] buffer, int offset, int length, SocketAddress address):与前一个构造器类似,但是接收者的名字和端口号包含在SocketAddress参数中。
    注意六个构造器都带有一个字节数组做参数。当接收包时,该数组开始是空,然后被接收的数据报包填充。当发送包时,字节数组存储要发送的包的数据。
    DatagramPacket类包含了数据报包不同属性的get和set方法:
    	public byte [] getData():返回数据缓冲区。
    	public void setData(byte [] buffer):设置包数据。
    	public int getLength():返回将要发送或接收到的数据的长度。
    	public void setLength(int length):设置将要发送或者接收到的数据的长度。
    	public SocketAddress getSocketAddress():返回消息要发送到的或者发出此消息的远程主机的地址。
    	public void setSocketAddress(SocketAddress address):设置消息要发送到的或者发出消息的远程主机的地址。
    
              **URL类与URLConnection类**
    本章迄今为止,我们已经讨论了在Java中如何使用套接字和数据报包来创建网络应用。在本节中,我们将学习如何编写与URL资源进行通讯的Java程序。URL(Uniform Resource Locator)代表统一资源定位,代表万维网上的一个资源,例如一个网页或者一个FTP目录。
    一个URL实际上是一类URI(Uniform Resource Identifier,统一资源标识符)。URI标识一个资源,但是不包括如何访问该资源的信息。URL标识一个资源以及访问该资源的协议。URI在java中使用java.net.URI类代表。
    一个URL可以分为如下几个部分:
    协议://主机:端口/路径?查询字符串#锚点引用
    
    这里,路径也称为文件名,主机也称为授权。协议包含HTTP、HTTPS、FTP和File。
    java.net.URL类代表一个URL。URL类有如下几个构造器用于创建URL:
    	public URL(String protocol, String host, int port, String file) throws MalformedURLException:根据指定 protocol、host、port 号和 file 创建 URL 对象。
    	public URL(String protocol, String host, String file) throws  MalformedURLException:与前一构造器相同,但是用的是指定协议的默认端口。
    	public URL(String url) throws MalformedURLException:根据给定的字符串创建URL对象。
    URL类中有很多方法用于访问URL的不同部分,常用的方法如下:
    	public String getPath():获取此URL的路径部分。
    	public String getQuery():获取此 URL 的查询部分。
    	public String getAuthority():获取此 URL 的授权部分。
    	public int getPort():获取此 URL 的端口号。
    	public int getDefaultPort():获取与此 URL 关联协议的默认端口号。
    	public String getProtocol():获取此 URL 的协议名称。
    	public String getHost():获取此 URL 的主机名。
    	public String getFile():获取此 URL 的文件名。
    	public String getRef():获取此 URL 的锚点。
    	public URLConnection openConnection() throws IOException:打开一个到该URL的连接,允许客户端与该资源进行通讯。
    
    使用URL类的openConnection()方法,可以连接到一个URL,并与资源进行通讯。openConnection()方法返回一个java.net.URLConnection,URLConnection是一个抽象类,其子类代表不同类型的URLConnection。例如,如果我们连接到一个HTTP协议的URL,那么openConnection()方法就返回一个HttpURLConnection对象。如果连接到一个代表JAR额外年间的URL,那么openConnection()方法就返回一个JarURLConnection对象。
    URLConnection类有多个用于设置或者判断连接信息的方法,包括:
    	public void setDoInput(boolean input):将此 URLConnection 的 doInput 字段的值设置为指定的值。URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 true,因为客户端通常是从URLConnection中读取。
    	public void setDoOutput(boolean output):将此 URLConnection 的 doOutput 字段的值设置为指定的值。如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 false,因为很多URL类型不支持写入数据。
    	public InputStream getInputStream() throws IOException:返回从资源读取的URLConnection的输入流。
    	public OutputStream getOutputStream() throws IOException:返回写入到此连接的输出流。返回写入到资源的URLConnection的输出流。
    	public URLgetURL():返回此URLConnection对象要连接到的URL。
    URLConnection类还包含了一些访问连接头信息的方法,让我们可以判断URL内容的类型和长度、最后更改的日子、内容编码等等。更多的方法,请参考JDK文档中URLConnection的详细说明。
    
    展开全文
  • JAVA网络编程

    千次阅读 2018-03-17 19:51:41
    【TX】Java网络编程提供了两种通讯协议:TCP【传输控制协议】和UDP【数据报协议】。这两种都属于传输层协议,TCP是可靠的,传输前会采用“三次握手”的方式建立连接,以保证传输的可靠性;UDP是不可靠的传输协议,即...

    【TX】Java网络编程提供了两种通讯协议:TCP【传输控制协议】和UDP【数据报协议】。这两种都属于传输层协议,TCP是可靠的,传输前会采用“三次握手”的方式建立连接,以保证传输的可靠性;UDP是不可靠的传输协议,即发出去的数据不一定能接受的到,网上聊天工具一般采用此种协议。

    一:基本概念

    1:【IP】IP是互联网上每一台计算机的唯一标识,使用32位长度的二进制数据表示。

    IP地址=网络地址+主机地址

        网络号:用于识别主机所在的网络。

        主机号:用于识别该网络中的主机。

    IP地址分为5类,在开发中经常使用127.0.0.1表示本机的IP地址。

    我们先看一下JAVA对于IP的支持,获取本机或远程IP及主机名:

    		InetAddress Inet=InetAddress.getLocalHost();//获取本机的InetAddress对象
    		InetAddress Inet1=InetAddress.getByName("www.baidu.com");//通过主机名获取InetAddress对象
    		
    		String hostName = Inet.getHostName();//获取本机名
    		String hostAddress = Inet.getHostAddress();//获取本机的IP
    		System.out.println(hostName+":"+hostAddress);
    		
    		String hostName1 = Inet1.getHostName();
    		String hostAddress1 = Inet1.getHostAddress();
    		System.out.println(hostName1+":"+hostAddress1);
    		
    		boolean reachable = Inet.isReachable(2000);//判断地址是否可以到达,同时指定超时时间

    执行结果:

    Lenovo-PC:176.132.251.36
    www.baidu.com:115.239.210.27
    true

    2:【URL】Uniform Resouce Locator  统一资源定位符。

    public class URLTest {
    	@SuppressWarnings("resource")
    	public static void main(String[] args) throws Exception {
    		URL url=new URL("http://news.sina.com.cn/c/nd/2018-03-17/doc-ifyshfuq6442303.shtml");
    		
    		InputStream openStream = url.openStream();//读取URL内容
    		Scanner scanner = new Scanner(openStream);//
    		scanner.useDelimiter("\n");//设置读取分割符
    		while(scanner.hasNext()){
    			System.out.println(scanner.next());
    		}
    		
    		URLConnection connection = url.openConnection();//建立连接
    		int contentLength = connection.getContentLength();//获取内容长度
    		String contentType = connection.getContentType();//获取内容类型
    
    		System.out.println(contentLength);
    		System.out.println(contentType);
    	}
    }

    程序执行结果:

    ..............省略.............
    <!-- body code end -->
    </body>
    </html>
    
    49517
    text/html
    

    可以发现下载下来的内容都是页面的HTML代码。

    在使用URL访问时,如果URL全部为英文,则可以正常显示,如果包含有中文,则会进行编码。在JAVA中如果要完成编码与解码就需要使用URLEncode和URLDecode两个类。URLEncode可以对传递的内容进行编码,URLDecode可以对传递的内容进行解码。

                    String key="中文网名";
    		String encode = URLEncoder.encode(key,"UTF-8");
    		System.out.println("编码之后的内容:"+encode);
    		String decode = URLDecoder.decode(encode,"UTF-8");
    		System.out.println("解码之后的内容:"+decode);

    程序执行结果:

    编码之后的内容:%E4%B8%AD%E6%96%87%E7%BD%91%E5%90%8D
    解码之后的内容:中文网名




    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,900
精华内容 13,560
关键字:

java网络编程

java 订阅