java网络编程基础

计算机唯一标示——ip

我们知道每台计算机都有自己的ip地址,二而且这个ip地址是唯一的(在dos下键入ipconfig可以查看本机ip地址)该ip是用来唯一标示计算机的,这样才可以在网络上找到并访问该计算机上的资源。

所以ip是网络编程的基础,在java API中提供了两个类来标示ip地址 InetAddress、InetSocketAddress

InetAddress类只包含计算机的地址和主机名,InetSocketAddress类另外还标示端口号。

端口:操作系统提供了66035个端口为外界提供服务,外部网路想要访问该计算机上的资源必须同过端口上的监听程序进行处理后才能获取,(1~1024为系统预留端口不建议使用)

 1 package cn.wz.net.demo.ip;
 2 
 3 import java.net.InetAddress;
 4 import java.net.UnknownHostException;
 5 
 6 /**
 7  * Created by WangZhe on 2017/5/10.
 8  * InetAddress代表一个主机的ip地址(不包括端口号)
 9  */
10 public class InetAddressDemo {
11     public static void main(String[] args) throws UnknownHostException {
12         /*InetAddress ia=InetAddress.getLocalHost();*///返回本地主机(对应的InetAddress对象实例)
13         InetAddress ia=InetAddress.getByName("www.bing.com");//根据提供的主机名(域名或具体ip)创建InetAddress对象实例
14         System.out.println(ia.getHostName());
15         System.out.println(ia.getHostAddress());
16         System.out.println(ia.getCanonicalHostName());
17     }
18 }
InetAddressDemo
 1 package cn.wz.net.demo.ip;
 2 
 3 import java.net.InetSocketAddress;
 4 
 5 /**
 6  * Created by WangZhe on 2017/5/10.
 7  * InetSocketAddress代表一个主机的ip地址(包括端口号)
 8  */
 9 public class InetSocketAddressDemo {
10     public static void main(String[] args) {
11         InetSocketAddress isa=new InetSocketAddress("cn.bing.com",8080);//根据提供的主机地址和端口号创建InetSocketAddress对象
12         System.out.println(isa.getHostName());//获取主机地址
13         System.out.println(isa.getAddress().getHostAddress());//先获取对应的InetAddress对象在获取对应的ip
14     }
15 }
InetSocketAddress

网络资源路径限定符--URL

URL是网络中资源的唯一标示限定符,每一个url都标示一个资源。该对象一般用于从网络中爬去某些资源,如下一个爬取bing首页源代码的demo

 1 package cn.wz.net.demo.url;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.io.InputStreamReader;
 7 import java.net.MalformedURLException;
 8 import java.net.URL;
 9 
10 /**
11  * Created by WangZhe on 2017/5/10.
12  */
13 public class URLDemo {
14     public static void main(String[] args) throws IOException {
15         URL url=new URL("http://cn.bing.com");
16         System.out.println("全路径:"+url.getPath());
17         System.out.println("域名:"+url.getHost());
18         System.out.println("端口:"+url.getPort());
19         System.out.println("资源文件:"+url.getFile());
20         System.out.println("参数:"+url.getQuery());
21         System.out.println("协议名称"+url.getProtocol());
22         InputStream inputStream = url.openStream();
23         BufferedReader br=new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
24         String msg=null;
25         while ((msg=br.readLine())!=null){
26             System.out.println(msg+"\n");
27         }
28         br.close();
29     }
30 
31 }
URLDemo

网络中的快递员--数据传输协议

  有了数据传输协议个个计算机上的数据才能在网络中进行传输,如我们在浏览器中访问bing的首页是浏览器就需要从bing的服务器上获取数据,当我们搜索新闻时浏览器又需要将搜索框中我们输入的内容发送个服务器,这个数据交换的过程就是使用的TCP协议(http及https都是tcp协议封装后的结果)。

udp协议

 udp协议相对于tcp协议而言,其传输速度要快的多,但其不能保证其数据一定能安全到达另一端,有可能出现数据丢失的情况,因为其不需要连接如果找不到另一端来接收就会出现数据丢失的情况,但正是由于去不需要连接所以传输速度比TCP协议要快得多!udp协议一般被用于局域网内的屏幕分享和直播平台之类的场景。

java中提供的udp协议的实现类是DataGramSocket类,该类用于发送和接收udp协议的数据,而通过udp协议发送的数据必须要打成数据包(DataGramPacket)才能被DataGramSocket类进行发送

下面来看下DataGramSocket类的一些常用方法和构造,其提供了多个构造的重载来创建该对象,

我们一般用的较多的是只传入端口号的那个构造,该构是在本机上建立监听,其它的构造也可以自己制定监听的地址,而实际上第二个构造和第三个构造本质上也是使用第四个构造来创建的。可以自己翻下源码。

常用方法:

DataGramPacket类的构造

方法摘要

 1 package cn.wz.net.demo.udp;
 2 
 3 import java.io.DataInputStream;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.net.DatagramPacket;
 7 import java.net.DatagramSocket;
 8 import java.net.SocketAddress;
 9 import java.net.SocketException;
10 
11 /**
12  * Created by WangZhe on 2017/5/10.
13  */
14 public class Server {
15     public static void main(String[] args) throws IOException {
16         DatagramSocket dgs=new DatagramSocket(8888);
17         for (;;) {
18             byte[] content = new byte[1024];
19             DatagramPacket dgp=new DatagramPacket(content,content.length);
20             dgs.receive(dgp);
21             String string = new String(content,"UTF-8");
22             if(string!=null&&!string.equals(""))
23                 System.out.println(string);
24         }
25     }
26 }
demo(Server端)
 1 package cn.wz.net.demo.udp;
 2 
 3 import java.io.DataInputStream;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.net.*;
 7 
 8 /**
 9  * Created by WangZhe on 2017/5/10.
10  */
11 public class Client {
12     public static void main(String[] args) throws IOException, InterruptedException {
13         DatagramSocket dgs=new DatagramSocket(9999);
14         for (int i=1;;i++) {
15             byte[] msg=new byte[1024];
16             InputStream in = System.in;
17             DataInputStream dis = new DataInputStream(in);
18             dis.read(msg);
19             DatagramPacket dgp=new DatagramPacket(msg,msg.length, InetAddress.getLocalHost(),8888);
20             dgs.send(dgp);
21         }
22 
23     }
24 }
demo(Client端)

效果图

 

TCP协议

tcp协议与UDP协议想法它是有链接的,TCP协议传输协议需要进行三次握手,也就是我们常说的浏览器从服务其请求数据所说的三次握手。

java提供的tcp实现类为Socket和ServerSocket顾名思义Socket主要表示客户端而ServerSocket主要表示服务端。这里他们的构造和方法就不在介绍了,自己翻API吧(犯懒了,不想写。。。)这里直接上一个简单demo

package cn.wz.net.demo.tcp;

import cn.wz.net.demo.tcp.util.ReadMessage;
import cn.wz.net.demo.tcp.util.SendMessage;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * Created by WangZhe on 2017/5/11.
 */
public class Client {
    public static void main(String[] args) throws IOException {
        Socket s=new Socket();//创建Socket对象
        s.connect(new InetSocketAddress("localhost", 9999));//创建连接
        SendMessage sm=new SendMessage(s);//创建一个循环发送数据的任务
        new Thread(sm).start();//启动一个线程执行发送数据的任务
        ReadMessage rm=new ReadMessage(s);//创建一个循环接受数据的任务
        new Thread(rm).start();//启动线程执行接受数据的任务
    }
}
demo(Client端)
package cn.wz.net.demo.tcp;

import cn.wz.net.demo.tcp.util.ReadMessage;
import cn.wz.net.demo.tcp.util.SendMessage;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by WangZhe on 2017/5/11.
 */
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket sSocket=new ServerSocket(9999);//创建服务端Socket
        for (;;) {
            Socket accept = sSocket.accept();//接受请求
            ReadMessage rm = new ReadMessage(accept);
            new Thread(rm).start();
            SendMessage message=new SendMessage(accept);
            new Thread(message).start();
        }
    }
}
demo(Server端)
package cn.wz.net.demo.tcp.util;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.locks.ReadWriteLock;

/**
 * Created by WangZhe on 2017/5/11.
 */
public class ReadMessage implements Runnable {
    /**
     * 数据输入流用于保存接收到的数据
     */
    private DataInputStream dis;
    /**
     * 标示该任务是否正常执行
     */
    private boolean isRuning=true;
    protected ReadMessage() {
    }

    public ReadMessage(Socket socket) {
        try {
            this.dis = new DataInputStream(socket.getInputStream());
        } catch (IOException e) {
            isRuning=false;
            CloseUtil.closeAll(dis);
        }
    }

    /**
     * 读取数据
     * @return 读取到的字符串
     */
    protected String read(){
        try {
            return dis.readUTF();
        } catch (IOException e) {
            isRuning=false;
            CloseUtil.closeAll(dis);
        }
        return null;
    }

    public void run() {
        while (isRuning)
            System.out.println(read());


    }
}
demo(ReadMessage )
package cn.wz.net.demo.tcp.util;

import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by WangZhe on 2017/5/11.
 */
public class SendMessage implements Runnable{


    /**
     * 输出流用于socket发送数据
     */
    private DataOutputStream dos;
    /**
     * 读取流用于获取用户从控制台输入的字符
     */
    private BufferedReader br;
    /**
     * 标示线程是否正常运行
     */
    private boolean isRuning=true;
    /**
     * 初始化br对象
     */
    protected SendMessage() {
        br=new BufferedReader(new InputStreamReader(System.in));
    }

    /**
     * 创建SendMessage对象并进行初始化
     * @param socket
     */
    public SendMessage(Socket socket)   {
        this();
        try {
            this.dos=new DataOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            isRuning=false;
            CloseUtil.closeAll(dos,br);
        }
    }

    /**
     * 发送数据
     * @param message
     */
    protected void send(String message){
        try {
            dos.writeUTF(message);
            dos.flush();
        } catch (IOException e) {
            /*e.printStackTrace();*/
            isRuning=false;
            CloseUtil.closeAll(dos);
        }
    }
    /**
     * 获取用户输入的数据请转化成字符串
     * @return
     */
    protected synchronized String  getMessage(){
        try {
            return br.readLine();
        } catch (IOException e) {
            isRuning=false;
            CloseUtil.closeAll(dos,br);
        }
        return null;
    }
    /**
     * 线程任务方法
     */
    public void run() {
        while (isRuning)
            send(getMessage());
    }

}
demo(SendMessage )

效果图

 

 Server端像Client端发送数据

TCP协议与HTTP(/HTTPS)协议的区别

很多人都分不清这两者之间的区别,前边儿也已经说了Http协议实际上就是对TCP协议的封装,我们正常的TCP两链接中携带的数据时很广泛的且没有固定的格式,浏览器没办法进行通用的解析(浏览器实际上就是一个Socket客户端)。也就是说一个每个浏览器都有自己解析数据的方式且相互之间并不统一,从而导致了互联网一直停滞不前,所以就有了http协议的诞生,http协议封装了TCP协议。简单的说也就是:TCP协议规定了数据的传输方式,而http协议规定了连接中数据的格式。

 

posted @ 2017-05-15 17:21  王哲(真)  阅读(350)  评论(0编辑  收藏  举报