`
Jack22
  • 浏览: 133317 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java网络编程

 
阅读更多

Java的基本网络支持

 

1.    InetAddress.java

Java中的InetAddress是一个代表IP地址的对象。IP地址可以由字节数组和字符串来分别表示,InetAddress将IP地址以对象的形式进行封装,可以更方便的操作和获取其属性。InetAddress没有构造方法,可以通过两个静态方法获得它的对象。该类的两个直接子类Inet4AddressInet6Address 分别用于标识32位IP地址跟64位IP地址 测试代码:

 

        InetAddress ip = InetAddress.getByName("http://jack22.iteye.com");
        //判断是否可达  
        System.out.println("oneedu是否可达:" + ip.isReachable(2000));
        //获取该InetAddress实例的IP字符串  
        System.out.println(ip.getHostAddress());  
        //根据原始IP地址(字节数组形式)来获取对应的InetAddress实例  
	InetAddress local = InetAddress.getByAddress(new byte[]{127,0,0,1});  
        System.out.println("本机是否可达:" + local.isReachable(5000));  
        //获取该InetAddress实例对应的全限定域名  
        System.out.println(local.getCanonicalHostName()); 	

 

URL和URLConnection

统一资源定位符(URL,英语UniformResourceLocator的缩写)也被称为网页地址,是因特网上标准的资源的地址。URL可以被认为是指向互联网资源的“指针”,通过URL可以获得互联网资源相关信息,包括获得URL的InputStream对象获取资源的信息,以及一个到URL所引用远程对象的连接URLConnection。

    URLConnection对象可以向所代表的URL发送请求和读取URL的资源。通常,创建一个和URL的连接,需要如下几个步骤:
    a. 创建URL对象,并通过调用openConnection方法获得URLConnection对象;
    b. 设置URLConnection参数和普通请求属性;
    c. 向远程资源发送请求;
    d. 远程资源变为可用,程序可以访问远程资源的头字段和通过输入流来读取远程资源返回的信息。
    这里需要重点讨论一下第三步:如果只是发送GET方式请求,使用connect方法建立和远程资源的连接即可;如果是需要发送POST方式的请求,则需要获取URLConnection对象所对应的输出流来发送请求。这里需要注意的是,由于GET方法的参数传递方式是将参数显式追加在地址后面,那么在构造URL对象时的参数就应当是包含了参数的完整URL地址,而在获得了URLConnection对象之后,就直接调用connect方法即可发送请求。
而POST方法传递参数时仅仅需要页面URL,而参数通过需要通过输出流来传递。另外还需要设置头字段。以下是两种方式的代码。

 

//1. 向指定URL发送GET方法的请求  
           String urlName = url + "?" + param;  
            URL realUrl = new URL(urlName);  
            //打开和URL之间的连接  
            URLConnection conn = realUrl.openConnection();  
            //设置通用的请求属性  
            conn.setRequestProperty("accept", "*/*");   
            conn.setRequestProperty("connection", "Keep-Alive");   
            conn.setRequestProperty("user-agent",   
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");   
            //建立实际的连接  
            conn.connect();   
 
//2. 向指定URL发送POST方法的请求  
           URL realUrl = new URL(url);  
            //打开和URL之间的连接  
            URLConnection conn = realUrl.openConnection();  
            //设置通用的请求属性  
            conn.setRequestProperty("accept", "*/*");   
            conn.setRequestProperty("connection", "Keep-Alive");   
            conn.setRequestProperty("user-agent",   
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");   
            //发送POST请求必须设置如下两行  
            conn.setDoOutput(true);  
            conn.setDoInput(true);  
            //获取URLConnection对象对应的输出流  
            out = new PrintWriter(conn.getOutputStream());  
            //发送请求参数  
            out.print(param);  
 

 

 

URLDecoder和URLEncoder

这两个类可以别用于将application/x-www-form-urlencoded MIME类型的字符串转换为普通字符串,将普通字符串转换为这类特殊型的字符串。使用URLDecoder类的静态方法decode()用于解码,URLEncoder类的静态方法encode()用于编码。具体使用方法如下。

 

        //将application/x-www-form-urlencoded字符串  
        //转换成普通字符串  
         String keyWord = URLDecoder.decode(  
            "%E6%9D%8E%E5%88%9A+j2ee", "UTF-8");  
        System.out.println(keyWord);  
        //将普通字符串转换成  
        //application/x-www-form-urlencoded字符串  
        String urlStr = URLEncoder.encode(  
            "ROR敏捷开发最佳指南" , "GBK");  
        System.out.println(urlStr); 
 

基于TCP协议的网络编程

 

TCP协议是一种可靠的通络协议,通信两端的Socket使得它们之间形成网络虚拟链路,两端的程序可以通过虚拟链路进行通讯。Java使用socket对象代表两端的通信端口,并通过socket产生的IO流来进行网络通信。

 


2.1 ServerSocket
    在两个通信端没有建立虚拟链路之前,必须有一个通信实体首先主动监听来自另一端的请求。ServerSocket对象使用accept()方法用于监听来自客户端的Socket连接,如果收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket对象。如果没有连接,它将一直处于等待状态。通常情况下,服务器不应只接受一个客户端请求,而应该通过循环调用accept()不断接受来自客户端的所有请求。
    这里需要注意的是,对于多次接收客户端数据的情况来说,一方面可以每次都在客户端建立一个新的Socket对象然后通过输入输出通讯,这样对于服务器端来说,每次循环所接收的内容也不一样,被认为是不同的客户端。另外,也可以只建立一次,然后在这个虚拟链路上通信,这样在服务器端一次循环的内容就是通信的全过程。
    服务器端的示例代码:

 

 

 

//创建一个ServerSocket,用于监听客户端Socket的连接请求  监听端口为30000
        ServerSocket ss = new ServerSocket(30000);  
        //采用循环不断接受来自客户端的请求  
        while (true)  
        {  
            //每当接受到客户端Socket的请求,服务器端也对应产生一个Socket  
            Socket s = ss.accept();  
            //将Socket对应的输出流包装成PrintStream  
            PrintStream ps = new PrintStream(s.getOutputStream());  
            //进行普通IO操作  
            ps.println("您好,今天服务器的大姨夫来了!");  
            //关闭输出流,关闭Socket  
            ps.close();  
            s.close();  
        } 

 2.2 Socket

 

    使用Socket可以主动连接到服务器端,使用服务器的IP地址和端口号初始化之后,服务器端的accept便可以解除阻塞继续向下执行,这样就建立了一对互相连接的Socket。
    客户端示例代码:

 

       Socket socket = new Socket("127.0.0.1" , 30000);  
        //将Socket对应的输入流包装成BufferedReader  
        BufferedReader br = new BufferedReader(  
            new InputStreamReader(socket.getInputStream()));  
        //进行普通IO操作  
        String line = br.readLine();  
        System.out.println("来自服务器的数据:" + line);  
        //关闭输入流、socket  
        br.close();  
        socket.close(); 

 2.3 使用多线程

 

    在复杂的通讯中,使用多线程非常必要。对于服务器来说,它需要接收来自多个客户端的连接请求,处理多个客户端通讯需要并发执行,那么就需要对每一个传过来的Socket在不同的线程中进行处理,每条线程需要负责与一个客户端进行通信。以防止其中一个客户端的处理阻塞会影响到其他的线程。对于客户端来说,一方面要读取来自服务器端的数据,另一方面又要向服务器端输出数据,它们同样也需要在不同的线程中分别处理。
具体代码如下,服务器端:

 

public class MyServer  
{  
    //定义保存所有Socket的ArrayList  
    public static ArrayList<Socket> socketList = new ArrayList<Socket>();  
    public static void main(String[] args)   
        throws IOException  
    {  
        ServerSocket ss = new ServerSocket(30000);  
        while(true)  
        {  
            //此行代码会阻塞,将一直等待别人的连接  
            Socket s = ss.accept();  
            socketList.add(s);  
            //每当客户端连接后启动一条ServerThread线程为该客户端服务  
            new Thread(new ServerThread(s)).start();  
        }  
    }  
} 

 客户端:

 

public class MyClient  
{  
    public static void main(String[] args)  
        throws IOException   
    {  
        Socket s = s = new Socket("127.0.0.1" , 30000);  
        //客户端启动ClientThread线程不断读取来自服务器的数据  
        new Thread(new ClientThread(s)).start();  
        //获取该Socket对应的输出流  
        PrintStream ps = new PrintStream(s.getOutputStream());  
        String line = null;  
        //不断读取键盘输入  
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  
        while ((line = br.readLine()) != null)  
        {  
            //将用户的键盘输入内容写入Socket对应的输出流  
            ps.println(line);  
        }  
    } } 

 UDP协议的网络编程

UDP协议是一种不可靠的网络协议,它在通讯实例的两端个建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送和接受数据报的对象,Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送和接收的数据报。

 


3.1 使用DatagramSocket发送、接收数据
    DatagramSocket本身并不负责维护状态和产生IO流。它仅仅负责接收和发送数据报。使用receive(DatagramPacket p)方法接收,使用send(DatagramPacket p)方法发送。
    这里需要首先明确的是,DatagramPacket对象的构造。DatagramPacket的内部实际上采用了一个字节型数组来保存数据,它的初始化方法如下:

 

//接收端的DatagaramSocket内部包含一个空的数组,接收传递过来的数据报中的数组信息。可以通过DatagaramSocket对象的getData()方法返回的数组来获取其中的包含的数组。  
Private DatagaramSocket udpSocket=new DatagaramSocket(buf,buf.length);  
//发送端的DatagaramSocket内部包含一个将要传递的数组,同时需要包含目标IP和端口。如果初始化时传递的数组参数是空,可以通过调用DatagaramSocket对象的setData()方法设置内容。  
Private DatagaramSocket udpSocket=new DatagaramSocket(buf,buf.length,IP,PORT);  
udpSocket。setData(outBuf); 

  作为这两个方法的参数,作用和构造不同的。作为接收方法中的参数,DatagramPacket中的数组一个空的数组,用来存放接收到的DatagramPacket对象中的数组;而作为发送方法参数,DatagramPacket本身含有了目的端的IP和端口,以及存储了要发送内容的指定了长度的字节型数组。

    另外,DatagramPacket对象还提供了setData(Byte[] b)和Byte[] b= getData()方法,用于设置DatagramPacket中包含的数组内容和获得其中包含数组的内容。
    使用TCP和UDP通讯的编码区别:
    a. 在TCP中,目标IP和端口由Socket指定包含;UDP中,目标IP由DatagramPacket包含指定,DatagramSocket只负责发送和接受。
    b. 在TCP中,通讯是通过Socket获得的IO流来实现;在UDP中,则通过DatagramSocket的send和receive方法

 

3.2 使用MulticastSocket实现多点广播
    MulticastSocket是DatagramSocket的子类,可以将数据报以广播形式发送到数量不等的多个客户端。实现策略就是定义一个广播地址,使得每个MulticastSocket都加入到这个地址中。从而每次使用MulticastSocket发送数据报(包含的广播地址)时,所有加入了这个广播地址的MulticastSocket对象都可以收到信息。
    MulticastSocket的初始化需要传递端口号作为参数,特别对于需要接受信息的端来说,它的端口号需要与发送端数据报中包含的端口号一致。具体代码如下://创建用于发送、接收数据的MulticastSocket对象

            //因为该MulticastSocket对象需要接收,所以有指定端口  
            socket = new MulticastSocket(BROADCAST_PORT);  
            broadcastAddress = InetAddress.getByName(BROADCAST_IP);  
            //将该socket加入指定的多点广播地址  
            socket.joinGroup(broadcastAddress);  
            //设置本MulticastSocket发送的数据报被回送到自身  
            socket.setLoopbackMode(false);  
            //初始化发送用的DatagramSocket,它包含一个长度为0的字节数组  
            outPacket = new DatagramPacket(new byte[0] , 0 ,  
                broadcastAddress , BROADCAST_PORT); 

 使用代理服务器

Java中可以使用Proxy直接创建连接代理服务器,具体使用方法如下

 

public class ProxyTest  
{  
    Proxy proxy;  
    URL url;  
    URLConnection conn;  
    //从网络通过代理读数据  
    Scanner scan;  
    PrintStream ps ;  
    //下面是代理服务器的地址和端口,  
    //换成实际有效的代理服务器的地址和端口  
    String proxyAddress = "202.128.23.32";  
    int proxyPort;  
    //下面是你试图打开的网站地址  
    String urlStr = "http://www.oneedu.cn";  
 
    public void init()  
    {  
        try 
        {  
            url = new URL(urlStr);  
            //创建一个代理服务器对象  
            proxy = new Proxy(Proxy.Type.HTTP,  
                new InetSocketAddress(proxyAddress , proxyPort));  
            //使用指定的代理服务器打开连接  
            conn = url.openConnection(proxy);  
            //设置超时时长。  
            conn.setConnectTimeout(5000);  
            scan = new Scanner(conn.getInputStream());  
            //初始化输出流  
            ps = new PrintStream("Index.htm");  
            while (scan.hasNextLine())  
            {  
                String line = scan.nextLine();  
                //在控制台输出网页资源内容  
                System.out.println(line);  
                //将网页资源内容输出到指定输出流  
                ps.println(line);  
            }  
        }  
        catch(MalformedURLException ex)  
        {  
            System.out.println(urlStr + "不是有效的网站地址!");  
        }  
        catch(IOException ex)  
        {  
            ex.printStackTrace();  
        }  
        //关闭资源  
        finally 
        {  
            if (ps != null)  
            {  
                ps.close();  
            }  
        }  
    }  
 
    } 

  编码中的问题总结

 

  a. 双方初始化套接字以后,就等于建立了链接,表示双方互相可以知晓对方的状态。服务器端可以调用接收到的客户端套接字进行输入输出流操作,客户端可以调用自身内部的套接字对象进行输入输出操作。这样可以保持输入输出的流畅性。例如,客户端向服务器端发送消息时,可以隔一段的时间输入一段信息,然后服务器端使用循环不断的读取传过来的输入流。
    b. 对于可能出现阻塞的方法,例如客户端进行循环不断读取来自服务器端的响应信息时,如果此时服务器端并没有向客户端进行输出,那么读取的方法将处于阻塞状态,直到收到信息为止才向下执行代码。那么对于这样容易产生阻塞的代码,就需要将它放在一个单独的线程中处理。
    c. 有一些流是顺承的。例如,服务器端在收到客户端的消息以后,就将消息再通过输出流向其他所有服务器发送。那么,这个来自客户端的输入流和发向客户端的输出流就是顺接的关系,不必对它们分在两个不同的线程。
    d. println()方法对应readLine()。
    e. 在JFrame类中,一般不要将自己的代码写进main方法中,可以将代码写到自定义的方法中,然后在main方法中调用。

 

分享到:
评论
1 楼 scpcyzxb 2012-04-01  
[b]

    [*]

    [*]
[/b]

相关推荐

    Java网络编程案例教程习题参考答案 .pdf

    Java网络编程案例教程习题参考答案 Java_network_programming是Java编程语言中一个基础组件,用于实现网络通信。以下是Java网络编程案例教程习题参考答案中涉及到的知识点: 1. Socket编程:Socket是Java网络编程...

    Java网络编程/Java网络编程实例

    Java网络编程是Java开发中的重要领域,它涵盖了网络应用程序的设计、实现和调试。在这个主题下,我们可以探讨多个关键知识点: 1. **Java Socket编程**:Java的Socket类提供了基于TCP/IP协议的网络通信能力。通过...

    java网络编程第四版pdf

    《Java网络编程(第四版)》是一本深入探讨Java在互联网环境下的编程技术的经典书籍。本书旨在帮助读者理解和掌握如何利用Java语言进行高效、安全的网络通信。书中内容覆盖了从基本的网络概念到复杂的多线程编程,是...

    Java网络编程期末考试复习题库+答案

    Java网络编程是计算机科学中的一个重要领域,特别是在软件开发中,它涉及到如何通过网络进行数据传输和通信。在Java中,网络编程主要依赖于Java的Socket编程、ServerSocket、URL类以及NIO(非阻塞I/O)等核心API。这...

    Java网络编程实验报告.pdf

    "Java网络编程实验报告" 本实验报告主要介绍了Java网络编程的基本概念和实现方法,通过设计和实现一个简单的客户端/服务器应用程序,了解Java网络编程的基本原理和实现方法。 知识点1:Java 网络编程基础 Java ...

    java网络编程

    在本资料中,《Java网络编程》第三版提供了深入浅出的讲解,旨在帮助开发者提升对这一领域的理解。 1. **基础概念**: - **网络模型**:Java网络编程基于OSI七层模型和TCP/IP四层模型。理解这些模型有助于理解网络...

    Java网络编程(第4版)PDF

    《Java网络编程(第4版)》是一本深入探讨Java平台上的网络编程技术的专业书籍,适合想要提升Java通讯技术的学者阅读。此书全面覆盖了Java网络编程的基础和高级概念,帮助开发者理解如何利用Java语言构建高效、可靠的...

    [Java网络编程(第3版,2004)].(Java.Network.Prog.epub

    Java网络编程

    Java网络编程实践课程设计报告.pdf

    Java 网络编程实践课程设计报告 这是一份 Java 网络编程实践课程设计报告,旨在帮助学生掌握 Java 编程语言、图形化界面、多线程、网络和数据库等技术,并提高动手实践能力和书本知识学习。该课程设计报告涵盖了 ...

    Java网络编程实例(随书源代码)

    Java网络编程是开发分布式应用程序的关键技术,它允许程序通过网络发送和接收数据。《Java网络编程实例》这本书的源代码提供了丰富的示例,帮助读者深入理解这一领域。本压缩包包含的源代码覆盖了Java网络编程的各种...

    Java网络编程精解(孙卫琴)电子教案

    《Java网络编程精解》是孙卫琴老师的一本经典教程,主要涵盖了Java语言在网络编程领域的深度解析。这本书深入浅出地介绍了如何使用Java进行网络通信,包括基本的TCP/IP协议、套接字编程、多线程技术以及HTTP、FTP等...

    java网络编程.pdf

    java网络编程.pdf

    《Java网络编程实例:Java网络编程实例》

    Java网络编程是开发分布式应用程序的关键技术,它使得Java程序能够与其他设备、系统和服务进行通信。本书《Java网络编程实例:Java网络编程实例》显然聚焦于通过实际案例来教授这一核心技能。以下是一些主要的知识点...

    Java网络编程资料

    Java网络编程是开发分布式应用程序的关键技术,它允许Java程序与其他计算机进行通信,实现数据的交换。这份"Java网络编程资料"包含三个重要的学习资源:关于Socket套接字的"Java套接字编程.chm"、关于网络协议特别是...

    Java网络编程.chm

    本资源为"Java网络编程.chm",是一本关于Java网络编程的电子书,以实例驱动的方式深入讲解了相关知识。 首先,我们要理解Java在网络编程中的基础——IO流。Java中的IO流分为字节流和字符流,它们用于读写数据,包括...

    java网络编程源码

    Java网络编程是Java开发中的重要领域,它涵盖了网络通信的所有基本概念和技术,包括TCP/IP协议栈、套接字(Socket)编程、多线程、数据传输格式等。孙卫琴的《java网络编程》一书深入浅出地讲解了这些核心概念,并...

    JAVA网络编程大全,pdf版

    《JAVA网络编程大全》是一本全面且深入介绍Java网络编程技术的权威著作,旨在帮助读者掌握Java在构建网络应用程序中的核心概念和实践技巧。PDF版的书籍为学习者提供了便捷的电子阅读体验,随时随地都能深化对Java...

    java网络编程 PPT

    Java网络编程是Java开发中的重要领域,主要用于实现应用程序之间的通信,包括客户端-服务器架构、分布式系统以及互联网数据传输。这份“java网络编程 PPT”来自清华大学,无疑为学习这一主题提供了权威的参考资料。...

    java网络编程经典的学习书籍

    《Java网络编程》是编程领域的经典著作,尤其对于学习Java网络编程的初学者及进阶者来说,这本书具有很高的参考价值。它详细介绍了如何利用Java语言进行网络通信,涵盖了网络编程的基本概念、协议以及实现方法。 一...

Global site tag (gtag.js) - Google Analytics