Java-网络编程

一、网络编程相关类

1、InetAddress类

InetAddress类
此类表示互联网协议 (IP) 地址。JDK为InetAddress类提供了几个常用的静态方法。
1.1常用方法:

public static InetAddress getByName(String host)throws UnknownHostException;

在给定主机名的情况下确定主机的 IP 地址。

public static InetAddress getLocalHost()throws UnknownHostException

返回本地主机。

public static InetAddress[] getAllByName(String host)throws UnknownHostException

在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。

public boolean isReachable(int timeout) throws IOException。

测试是否可以达到该地址

例:

public static void main(String[] args) throws UnknownHostException {
    InetAddress inet1 = InetAddress.getByName("localhost");
    // localhost/127.0.0.1
    System.out.println(inet1);
    InetAddress inet2 = InetAddress.getByName("127.0.0.1");
    // /127.0.0.1
    System.out.println(inet2);
    InetAddress inet3 = InetAddress.getLocalHost();
    // PC201501271840/10.2.163.181
    System.out.println(inet3);
    InetAddress[] inet4 = InetAddress.getAllByName("localhost");
    for (InetAddress a : inet4) {
        // localhost/127.0.0.1
        // localhost/0:0:0:0:0:0:0:1
        System.out.println(a);
    }
}
2、URL和URLConnection类

2.1URL

统一资源定位符(Uniform Resource Locator),它是指向互联网资源的指针。JAVA提供了该API,方便我们进行网络通信。
格式:
protocol :// hostname[:port] / path /[?query]

(1)URL创建

URL ( String url)
  //url代表一个绝对地址,URL对象直接指向这个资源,如:
  URL urll=new URL(http://www.baidu.com);
URL ( URL baseURL , String relativeURL)
 // 其中,baseURL代表绝对地址,relativeURL代表相对地址。如:
URL urll=new URL(http://www.baidu.com);
  URL lib=new URL(urll , “qa/index.html”);
URL ( String protocol , String host , String file)
  //其中,protocol代表通信协议,host代表主机名,file代表文件名。如:
  new URL (“http” ,”www.baidu.com” , “qa/index.html”);
URL ( String protocol , String host , int port , String file)
  URL lib = new URL(“http”,”www.baidu.com”,80,”/test /test.asp”);

(2)常用方法

public static void main(String[] args) throws MalformedURLException {
    URL url = new URL("http://geek.csdn.net/news/detail/62555");
    System.out.println(url.getProtocol());//获取此 URL 的协议名称。
    System.out.println(url.getHost());//获取此 URL 的主机名(如果适用)。
    System.out.println(url.getPort());//获取此 URL 的端口号。
    //获取与此 URL 关联协议的默认端口号。
    //如果 URL 方案或 URL 的 URLStreamHandler 未定义默认的端口号,则返回 -1。 
    System.out.println(url.getDefaultPort());
    //获取此 URL 的文件名。
    //返回的文件部分将与 getPath() 相同,再加上 getQuery() 值的规范化形式(如果有)。
    //如果没有查询部分,此方法和 getPath() 将返回相同的结果。 
    System.out.println(url.getFile());
    //获取此 URL 的路径部分。
    System.out.println(url.getPath());
    //获取此 URL 的查询部分。
    System.out.println(url.getQuery());
    //获取此 URL 的授权部分。
    System.out.println(url.getAuthority());
    //获取页面内容
    InputStream stream = url.openStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream,"UTF-8"));
    String info = null;
    while((info = reader.readLine())!=null){
        System.out.println(info);
    }
}

2.2URLConnection

URLConnection类
抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。通常,创建一个到 URL 的连接需要几个步骤:

openConnection()connect()
对影响到远程资源连接的参数进行操作。与资源交互;查询头字段和内容。

1)通过在 URL 上调用 openConnection 方法创建连接对象。
2)处理设置参数和一般请求属性。
3)使用 connect 方法建立到远程对象的实际连接。
4)远程对象变为可用。远程对象的头字段和内容变为可访问。

使用以下方法修改设置参数:

  • setAllowUserInteraction
  • setDoInput
  • setDoOutput
  • setIfModifiedSince
  • setUseCaches

在建立到远程对象的连接后,以下方法用于访问头字段和内容:

  • getContent
  • getHeaderField
  • getInputStream
  • getOutputStream

某些头字段需要经常访问。以下方法:

  • getContentEncoding
  • getContentLength
  • getContentType
  • getDate
  • getExpiration
  • getLastModifed

2.3HttpURLConnection
HttpURLConnection类
支持 HTTP 特定功能的 URLConnection。HttpURLConnection是java的标准类,HttpURLConnection继承自URLConnection,可用于向指定网站发送GET请求、POST请求。

常用方法:

public InputStream getErrorStream()

如果连接失败但服务器仍然发送了有用数据,则返回错误流。典型示例是,当 HTTP 服务器使用 404 响应时,将导致在连接中抛出 FileNotFoundException,但是服务器同时还会发送建议如何操作的 HTML 帮助页。

public String getHeaderFieldKey(int n)

返回 头字段的键。有些实现可能将头字段视为特殊状态行,即由 HTTP 服务器返回的状态行。在此情况下,getHeaderField(0) 返回状态行,而 getHeaderFieldKey(0) 返回 null。

public String getHeaderField(int n)

返回 头字段的值。有些实现可能将头字段视为特殊状态行,即由 HTTP 服务器返回的状态行。
此方法可以与 getHeaderFieldKey 方法一起使用来迭代消息中的所有头。

public long getHeaderFieldDate(String name, long Default)

返回解析为日期的指定字段的值。
// 执行时间:0.067426919937134
// HTTP/1.1 200 OK
// Date: Mon, 21 Mar 2016 07:56:42 GMT
// Content-Type: application/json; charset=utf-8
// Transfer-Encoding: chunked
// Connection: close
// Status: 200 OK
// ETag: “b153bfb1f41dbe46510a779e118df473”
// Cache-Control: max-age=0, private, must-revalidate
// X-Runtime: 0.004817
// Server: Microsoft-IIS/6.0

public void setRequestMethod(String method)throws ProtocolException

设置 URL 请求的方法, GET 、POST 、HEAD、OPTIONS、PUT、DELETE、TRACE
以上方法之一是合法的,具体取决于协议的限制。默认方法为 GET

public int getResponseCode() throws IOException

从 HTTP 响应消息获取状态码

public String getResponseMessage()throws IOException

获取与来自服务器的响应代码一起返回的 HTTP 响应消息(如果有)。

例:用HttpURLConnection从网络中下载图片

public static void main(String[] args) throws Exception {
        URL url = new URL("http://b.hiphotos.baidu.com/image/h%3D200/sign=f336067c4d90f6031bb09b470913b370/08f790529822720e754768b77ccb0a46f31fabf6.jpg");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        int code = conn.getResponseCode();//获取消息状态码
        if(code == 200){
            InputStream input =conn.getInputStream();
            OutputStream output = new FileOutputStream("d:/1_copy3.jpg");
            byte[] bs = new byte[1024];
            int i;
            while((i=input.read(bs))!=-1){
                output.write(bs, 0, i);
            }
            System.out.println("图片下载完成");
            output.close();
            input.close();
        }
    }

二、基于TCP协议编程

1、Socket

Socket

此类实现客户端套接字。套接字是两台机器间通信的端点。

Scoket也叫套接字,其表示的是IP地址和端口号的组合。
网络编程主要就是指Socket编程,网络间的通信其实就是Socket间的通信,数据就通过IO流在两个Scoket间进行传递。

构造方法和常用方法

public Socket(String host,int port)

创建一个流套接字并将其连接到指定主机上的指定端口号。

public Socket(InetAddress address,int port)

创建一个流套接字并将其连接到指定 IP 地址的指定端口号

public void bind(SocketAddress bindpoint) throws IOException

将套接字绑定到本地地址。

public void close()

关闭此套接字。

public void connect(SocketAddress endpoint)

将此套接字连接到服务器。

public void connect(SocketAddress endpoint,int timeout)

将此套接字连接到服务器,并指定一个超时值。

public InputStream getInputStream()

返回此套接字的输入流。

public int getPort() 

返回此套接字连接到的远程端口。

2、ServerSocket

ServerSocket

此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

服务器套接字的实际工作由 SocketImpl 类的实例执行。应用程序可以更改创建套接字实现的套接字工厂来配置它自身,从而创建适合本地防火墙的套接字。

构造方法和常用方法

ServerSocket() 

创建非绑定服务器套接字。

ServerSocket(int port) 

创建绑定到特定端口的服务器套接字。

ServerSocket(int port, int backlog) 

利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。

ServerSocket(int port, int backlog, InetAddress bindAddr)

使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。

public Socket accept()

侦听并接受到此套接字的连接。

public InetAddress getInetAddress()

返回此服务器套接字的本地地址。

例:服务端代码:

public static void main(String[] args) throws IOException {
    ServerSocket server = new ServerSocket(8081);
    System.out.println("正在监听8081端口");
    Socket socket = null;
    while (true) {
        socket = server.accept();
        // 接收消息
        InputStream input = socket.getInputStream();
        byte[] bs = new byte[1024];
        int len = input.read(bs);
        String ip = socket.getInetAddress().getHostAddress();
        int port = socket.getPort();
        System.out.println("来自客户端" + ip + ":" + port + "的消息:"+ new String(bs, 0, len));
        // 返回消息
        OutputStream out = socket.getOutputStream();
        out.write("welcome".getBytes());
        socket.close();
    }
}

客户端代码:

public static void main(String[] args) throws UnknownHostException,IOException {
    String info = "helloooo,tcp";
    Socket socket = new Socket("localhost", 8081);
    // 发送消息
    OutputStream out = socket.getOutputStream();
    out.write(info.getBytes());
    // 接收消息
    InputStream input = socket.getInputStream();
    byte[] bs = new byte[1024];
    int len = input.read(bs);
    System.out.println("来自服务端消息:" + new String(bs, 0, len));
    socket.close();
}

例2:多个客户端连接服务端

服务端:

public static void main(String[] args) throws IOException {
    ServerSocket server = new ServerSocket(8080);
//      server.bind("10.2.163.255");
    System.out.println("正在监听8080端口");
    while (true) {
        Socket socket = server.accept();
        new LogicThread(socket).start();
    }
}

客户端:

public static void main(String[] args) throws UnknownHostException,IOException {
    while (true) {
        String info = "呵呵";
        Socket socket = new Socket("10.2.163.61", 8080);
        // 发送消息
        OutputStream out = socket.getOutputStream();
        out.write(info.getBytes());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//      接收消息
        InputStream input = socket.getInputStream();
        byte[] bs = new byte[1024];
        int len = input.read(bs);
        System.out.println("来自服务端消息:" + new String(bs, 0, len));
        Close.close(out,input,socket);
    }
}

关闭Socket工具类:

public class Close {
    public static void close(Closeable... closes) {
        for (Closeable close : closes) {
            if (close != null) {
                try {
                    close.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

public class Closeees {

}

三、基于UDP协议编程

1、DatagramSocket

DatagramSocket

此类表示用来发送和接收数据报包的套接字。

数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

构造方法和常用方法:

public DatagramSocket(int port) throws SocketException

创建数据报套接字并将其绑定到本地主机上的指定端口。

public DatagramSocket(int port,InetAddress laddr) throws SocketException

创建数据报套接字,将其绑定到指定的本地地址。

public DatagramSocket(SocketAddress bindaddr) throws SocketException

创建数据报套接字,将其绑定到指定的本地套接字地址。

public void bind(SocketAddress addr) throws SocketException

将此 DatagramSocket 绑定到特定的地址和端口,在创建DatagramSocket对象的时候就会默认绑定。

public void close()

关闭此数据报套接字。

public InetAddress getInetAddress()

返回此套接字连接的地址。如果套接字未连接,则返回 null。

public int getPort()

返回此套接字的端口。如果套接字未连接,则返回 -1。

public void receive(DatagramPacket p) throws IOException

从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。
此方法在接收到数据报前一直阻塞。数据报包对象的 length 字段包含所接收信息的长度。如果信息比包的长度长,该信息将被截短。

public void send(DatagramPacket p) throws IOException

从此套接字发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。

2、DatagramPacket

DatagramPacket类
此类表示数据报包。

数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。

构造方法和常用方法

public DatagramPacket(byte[] buf, int length)

构造 DatagramPacket,用来接收长度为 length 的数据包。

public DatagramPacket(byte[] buf,int length,InetAddress address,int port) 

构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

public DatagramPacket(byte[] buf,int offset,int length)

构造 DatagramPacket,用来接收长度为 length 的包,在缓冲区中指定了偏移量。

public DatagramPacket(byte[] buf,int length,SocketAddress address) throws SocketException

构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

例1:
客户端1代码:

public static void main(String[] args) throws IOException {
    int count = 0;
    String info = "helloooo,udp";
    DatagramSocket client = new DatagramSocket(30000);
    byte[] bs = info.getBytes();
    DatagramPacket p = new DatagramPacket(bs, bs.length,InetAddress.getByName("localhost"), 30001);
    client.send(p);
    client.close();
}

客户端2(相当于服务端作用)代码:

public static void main(String[] args) throws IOException {
    DatagramSocket client = new DatagramSocket(30001);
    byte[] buf = new byte[1024];
    DatagramPacket p = new DatagramPacket(buf, buf.length);
    client.receive(p);
    String ip = p.getAddress().getHostAddress();
    int port = p.getPort();
    byte[] data = p.getData();
    System.out.println("from "+ip+":"+port+" say:"+new String(buf,0,p.getLength()));
    client.close();
    }

例2:开启多线程进行通信
客户端1:

public static void main(String[] args) throws SocketException,UnknownHostException {
    // 赋值
    DatagramSocket socket = new DatagramSocket(30000);
    InetAddress address = InetAddress.getByName("10.2.163.181");
    int port = 30001;
    // 启动
    new SendThread(address, port, socket).start();
    new ReceiveThread(socket).start();
}

客户端2:

public static void main(String[] args) throws IOException {
    DatagramSocket socket = new DatagramSocket(30001);
    InetAddress address = InetAddress.getByName("10.2.163.181");
    int port = 30000;
    new SendThread(address, port, socket).start();
    new ReceiveThread(socket).start();
}

接收消息的线程:

public class ReceiveThread extends Thread {
    private DatagramSocket socket;

    public ReceiveThread(DatagramSocket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            byte[] bytes = new byte[1024];
            while (true) {
                DatagramPacket receive = new DatagramPacket(bytes, bytes.length);
                socket.receive(receive);
                System.out.println(receive.getAddress().getHostAddress()+"说:"
                + new String(bytes, 0, bytes.length));
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            socket.close();
        }
    }

}

发送消息的线程:

public class SendThread extends Thread {
    private InetAddress address;
    private int port;
    private DatagramSocket socket;
    private BufferedReader br;

    public SendThread(InetAddress address, int port, DatagramSocket socket) {
        this.address = address;
        this.port = port;
        this.socket = socket;
        this.br = new BufferedReader(new InputStreamReader(System.in));
    }

    @Override
    public void run() {
        try {
            while (true) {
                String info = br.readLine();
                byte[] bytes = info.getBytes();
                DatagramPacket send = new DatagramPacket(bytes, bytes.length,address, port);
                socket.send(send);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            socket.close();
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wwwjfplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值