JavaSE学习 第十七章 Java网络编程

1.计算机网络工作模式 和 通信协议参考模型

专用服务器结构(Server-Based)

又称为“工作站/文件服务器”结构,由若干台微机工作站与一台或多台文件服务器通过通信线路连接起来组成工作站

存取服务器文件,共享存储设备。

客户机/服务器模式(Client/Server,C/S)

其中一台或几台较大的计算机集中进行共享数据库的管理和存取,称为服务器,而将其它的应用处理工作分散到网络中其它微机上去做,构成分布式的处理系统。

对等式网络(Peer-to-Peer,P2P)

在拓扑结构上与专用Server与C/S相同。在对等式网络结构中,没有专用服务器每一个工作站既可以起客户机作用也可以起服务器作用。

协议分层:

2

2.常用网络通信协议 和  IP地址/域名/端口

TCP/IP协议

TCP (Transmission Control Protocol,传输控制协议)

IP (Internet Protocol,网际协议)

HTTP协议

HTTP(Hypertext Transfer Protocol,超文本传输协议)

FTP协议

FTP(File Transfer Protocol,文件传输协议)

SMTP协议

SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)

POP3/IMAP协议

POP3(Post Office Protocol - Version 3,邮局协议版本3)

IMAP(Internet Message Access Protocol,Internet消息访问协议)

IP地址

TCP/IP使用IP地址来标识源地址和目的地址

IP地址格式:166.111.78.98。

目 前 正 在 普 遍 使 用 的 IP 协 议 是 第 4 版 ( Version 4)的 , 称 为“IPv4”,新版本的(IPv6)协议也已开始推广。

域名(Domain Address)

便于记忆的、字符串形式,如“news.sina.com.cn”。

与IP地址间存在映射关系,由位于网络中的域名服务器(DNS,Domain Name Server)负责将域名解析为相应的IP地址。

端口(Port)

逻辑意义上的数据传输通道、或者说模拟通道。TCP/IP 协议约定,每台计算机拥有65536个这种逻辑通信端口。

端口号:用于标识这些端口的整数编号,其取值范围为0~65535。

3.相关API

JDK的java.net包中定义了与IP地址/域名有关的类

java.net.InetAddress

32位或128位无符号数字表示的IP地址

java.net.Inet4Address

继承了InetAddress类,以32位无符号数字表示的IPv4地址。其典型

表示形式是由圆点分隔开的4段、取值范围0~255的十进制数值,

例如"166.111.78.98"。

java.net.Inet6Address

继承了InetAddress类,以128位无符号数字表示的IPv6地址。其典

型表示形式是由冒号分隔开的8段、取值范围0000~FFFF的十六进

制数值,例如"1080:0:0:0:8:800:200C:417A"。

用法举例:

package v512;
import java.net.InetAddress;

public class TestInetAddress {
    public static void main( String args[]) {
        try{
            InetAddress ia = InetAddress.getLocalHost();
            showInfo(ia);
            
            ia = InetAddress.getByName("www.sina.com.cn");
            showInfo(ia);
        }catch(java.net.UnknownHostException e){
            e.printStackTrace();
        }
        
    }
    
    public static void showInfo(InetAddress ia){
        String name = ia.getHostName();
        String address = ia.getHostAddress();
        System.out.println(name);
        System.out.println(address);
        System.out.println("----------------");
    }
}

输出结果:

HJW
169.254.175.55
----------------
www.sina.com.cn
59.175.132.70
----------------

4.URL

URL(Uniform Resource Locator,统一资源定位器)用于表示Internet上资源的地址。

URL格式:<协议名><资源所在主机名>[:<端口号>]<资源名>

http://home.netscape.com/home/welcome.html

http://www.sun.com

http://java.cs.tsinghua.edu.cn:8888/

java.net包定义了对应的URL类,常用方法如下:

public URL(String spec);

public final InputStream openStream() throws IOException

用法举例:

package v512;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class URLReader {
    public static void main(String args[]) {
        // System.setProperty("http.proxyHost","192.168.1.1");
        // System.setProperty("http.proxyPort","11080");
        try {
            URL tirc = new URL("http://www.google.cn/");
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    tirc.openStream(), "utf-8"));//InputStreamReader字节流,读取的是远程资源(网页的文本内容)
            String s;
            while ((s = in.readLine()) != null)
                System.out.println(s);
            in.close();
        } catch (MalformedURLException e) {
            System.out.println(e);
        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

输出结果就是一个HTML文件的内容:

<!DOCTYPE html>
<html lang="zh">
  <meta charset="utf-8">
  <title>Google</title>
  <style>
    html { background: #fff; margin: 0 1em; }
    body { font: .8125em/1.5 arial, sans-serif; text-align: center; }
    h1 { font-size: 1.5em; font-weight: normal; margin: 1em 0 0; }
    p#footer { color: #767676; font-size: .77em; }
    p#footer a { background: url(http://www.google.cn/intl/zh-CN_cn/images/cn_icp.gif) top right no-repeat; padding: 5px 20px 5px 0; }
    ul { margin: 2em; padding: 0; }
    li { display: inline; padding: 0 2em; }
    div { -moz-border-radius: 20px; -webkit-border-radius: 20px; border: 1px solid #ccc; border-radius: 20px; margin: 2em auto 1em; max- 650px; min- 544px; }
    div:hover, div:hover * { cursor: pointer; }
    div:hover { border-color: #999; }
    div p { margin: .5em 0 1.5em; }
    img { border: 0; }
  </style>
  <div>
    <a href="http://www.google.com.hk/webhp?hl=zh-CN&amp;sourceid=cnhp"><img src="http://www.google.cn/landing/cnexp/google-search.png" alt="Google"></a>
    <h1><a href="http://www.google.com.hk/webhp?hl=zh-CN&amp;sourceid=cnhp"><strong id="target">google.com.hk</strong></a></h1>
    <p>请收藏我们的网址
  </div>
  <ul>
    <li><a href="http://www.google.cn/music?sourceid=cnhp">音乐</a>
    <li><a href="http://translate.google.cn/?sourceid=cnhp">翻译</a>
    <li><a href="http://www.google.cn/products?sourceid=cnhp">购物</a>
  </ul>
  <p id="footer">&copy;2011 - <a href="http://www.miibeian.gov.cn/">ICP证合字B2-20070004号</a>
  <script>
    var gcn=gcn||{};gcn.IS_IMAGES=(/images\.google\.cn/.exec(window.location)||window.location.hash=='#images'||window.location.hash=='images');
     gcn.HOMEPAGE_DEST='http://www.google.com.hk/webhp?hl=zh-CN&sourceid=cnhp';gcn.IMAGES_DEST='http://images.google.com.hk/imgcat/imghp?'+'hl=zh-CN&sourceid=cnhp';
     gcn.DEST_URL=gcn.IS_IMAGES?gcn.IMAGES_DEST:gcn.HOMEPAGE_DEST;gcn.READABLE_HOMEPAGE_URL='google.com.hk';
     gcn.READABLE_IMAGES_URL='images.google.com.hk';gcn.redirectIfLocationHasQueryParams=function(){if(window.location.search&&/google\.cn/.
     exec(window.location)&&!/webhp/.exec(window.location)){window.location=String(window.location).replace('google.cn','google.com.hk')}}();
     gcn.replaceHrefsWithImagesUrl=function(){if(gcn.IS_IMAGES){var a=document.getElementsByTagName('a');for(var i=0,len=a.length;i<len;i++)
     {if(a[i].href==gcn.HOMEPAGE_DEST){a[i].href=gcn.IMAGES_DEST}}}}();gcn.listen=function(a,e,b){if(a.addEventListener){a.addEventListener(e,b,false)}
     else if(a.attachEvent){var r=a.attachEvent('on'+e,b);return r}};gcn.stopDefaultAndProp=function(e){if(e&&e.preventDefault){e.preventDefault()}
     else if(window.event&&window.event.returnValue){window.eventReturnValue=false;return false}if(e&&e.stopPropagation){e.stopPropagation()}
     else if(window.event&&window.event.cancelBubble){window.event.cancelBubble=true;return false}};gcn.resetChildElements=function(a)
     {var b=a.childNodes;for(var i=0,len=b.length;i<len;i++){gcn.listen(b[i],'click',gcn.stopDefaultAndProp)}};gcn.redirect=function()
     {window.location=gcn.DEST_URL};gcn.setInnerHtmlInEl=function(a){if(gcn.IS_IMAGES){var b=document.getElementById(a);
     if(b){b.innerHTML=b.innerHTML.replace(gcn.READABLE_HOMEPAGE_URL,gcn.READABLE_IMAGES_URL)}}};
    gcn.listen(document, 'click', gcn.redirect);
    gcn.setInnerHtmlInEl('target');
  </script>

5.Socket 网络编程

两个进程间可以通过一个双向的网络通信连接实现数据交换,这种通信链路的端点被称为“套接字”(Socket)。

Socket通常用来实现Client-Server连接。

建立连接时所需的寻址信息:

①远程计算机的机器名或IP地址

②试图连接的端口号(Port number)

java.net包中定义的两个类Socket和ServerSocket,分别用来实现双向连接的client和server端。

Socket通信模型

1

编程步骤:

  1. 建立网络连接;
  2. 打开连接到Socket的输入/输出流;
  3. 通过已打开的I/O流进行数据读/写操作;
  4. 关闭已打开的I/O流和Socket。

用法举例:

服务器端:

package v512;
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;

public class TestServer {
    public static void main(String args[]) {
        try {        
            ServerSocket s = new ServerSocket(8888);
            while (true) {
                Socket s1 = s.accept();
                OutputStream os = s1.getOutputStream();
                DataOutputStream dos = new DataOutputStream(os);
                dos.writeUTF("你好,客户端地址信息: " + s1.getInetAddress()
                    + "\t客户端通信端口号: " + s1.getPort());
                dos.writeUTF("再见!");
                dos.close();
                s1.close();
            }
        }catch (IOException e) {
            e.printStackTrace();        
        }
    }
}

客户端:

package v512;
import java.io.*;
import java.net.Socket;

public class TestClient {
    public static void main(String args[]) {
        try {
            Socket s1 = new Socket("127.0.0.1", 8888);
            InputStream is = s1.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            System.out.println(dis.readUTF());
            System.out.println(dis.readUTF());
            dis.close();
            s1.close();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

你好,客户端地址信息: /127.0.0.1    客户端通信端口号: 53036
再见!

升级版本:两端可以自由的发送信息

服务器端:

package v512.chp17.test5;
import java.io.*;
import java.net.*;

public class TestServer {
    public static void main(String args[]) {
        try {        
            ServerSocket s = new ServerSocket(8888);
            Socket s1 = s.accept();
            OutputStream os = s1.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            InputStream is = s1.getInputStream();
            DataInputStream dis = new DataInputStream(is);

            new MyServerReader(dis).start();            
            new MyServerWriter(dos).start();
        }catch (IOException e) {
            e.printStackTrace();        
        }
    }
}

class MyServerReader extends Thread{
    private DataInputStream dis;
    public MyServerReader(DataInputStream dis ){
        this.dis = dis;    
    }
    public void run(){
        String info;
        try{
            while(true){
                info = dis.readUTF();
                System.out.println("对方说: " + info);
                if(info.equals("bye")){
                    System.out.println("对方下线,程序退出!");
                    System.exit(0);
                }
            }        
        }catch (IOException e) {
            e.printStackTrace();        
        }    
    }     
}

class MyServerWriter extends Thread{
    private DataOutputStream dos;
    public MyServerWriter(DataOutputStream dos){
        this.dos = dos;    
    }
    public void run(){
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        String info;
        try{
            while(true){
                info = br.readLine();
                dos.writeUTF(info);
                if(info.equals("bye")){
                    System.out.println("自己下线,程序退出!");
                    System.exit(0);
                }
            }        
        }catch (IOException e) {
            e.printStackTrace();        
        }    
    }     
}

客户端:

package v512.chp17.test5;
import java.io.*;
import java.net.*;

public class TestClient {
    public static void main(String args[]) {
        try {        
            Socket s1 = new Socket("127.0.0.1",8888);
            InputStream is = s1.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            OutputStream os = s1.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);

            new MyClientReader(dis).start();            
            new MyClientWriter(dos).start();
        }catch (IOException e) {
            e.printStackTrace();        
        }
    }
}

class MyClientReader extends Thread{
    private DataInputStream dis;
    public MyClientReader(DataInputStream dis ){
        this.dis = dis;    
    }
    public void run(){
        String info;
        try{
            while(true){
                info = dis.readUTF();
                System.out.println("对方说: " + info);
                if(info.equals("bye")){
                    System.out.println("对方下线,程序退出!");
                    System.exit(0);
                }
            }        
        }catch (IOException e) {
            e.printStackTrace();        
        }    
    }     
}

class MyClientWriter extends Thread{
    private DataOutputStream dos;
    public MyClientWriter(DataOutputStream dos){
        this.dos = dos;    
    }
    public void run(){
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        String info;
        try{
            while(true){
                info = br.readLine();
                dos.writeUTF(info);
                if(info.equals("bye")){
                    System.out.println("自己下线,程序退出!");
                    System.exit(0);
                }
            }        
        }catch (IOException e) {
            e.printStackTrace();        
        }    
    }     
}

测试结果:

3

6.非阻塞式IO

暂未研究。。。

原文地址:https://www.cnblogs.com/yinger/p/2160206.html