2019-04-02

作者: DreamPath | 来源:发表于2019-04-05 18:25 被阅读5次

网络编程基础部分整理

Ip地址:InetAddress

  • 网络中设备的标识:不宜记忆,可以用主机(服务器)名
  • 本地回环地址:127.0.0.1 主机名:localhost
  • 端口号:用于标识进程的逻辑地址,不同进程的标识
  • 有效端口:0~ 65535,其中0~1024被系统使用或者保留端口,也有的端口已经被占用了
  • 传输协议:TCP(传输控制协议),UDP(数据报文包协议)
  • 网址:http//:sina.com.cn
    tcp,udp
    (协议http//:+ 主机名sina + 通用域名com(commercial),中国的cn)
package internet_Adress;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 获取本地主机的IP地址和主机名
 * 获取其他主机地址和ip地址时,会遇到解析失败的情况。
 */
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {

        //ip地址对象      InetAddress
        //获取本地主机对象
        InetAddress ip1=InetAddress.getLocalHost();

        //输出ip地址和主机名
        System.out.println(ip1.getHostAddress()+"------"+ip1.getHostName());

        //根据ip地址获取该地址的主机名

        //注意: 如果是本地局域网下的非本机ip  主机名可能无法获取,因为需要进行解析
        InetAddress ip2=InetAddress.getByName("42.224.252.27");
        //根据主机名获取ip地址

        InetAddress ip3=InetAddress.getByName("DESKTOP-HVR3SSG");

        System.out.println(ip2.getHostAddress()+"------"+ip2.getHostName());
        System.out.println(ip3.getHostAddress()+"------"+ip3.getHostName());

    }
}
解析
  • 新浪网首页的访问,主机:http//:www.sina.com.cn
  • 新浪的新闻页面访问,子主机:http//:news.sina.com.cn
  • 新浪的运动体育访问,子主机:http//:sports.sina.com.cn

比如

  • 客户端输入:http//:www.sina.com.cn
    然后通过解析操作,去本地查表
  • 本地查表路径:C:\Windows\System32\drivers\etc\hosts
  • 当然本地主机存储的域名和主机名有限
  • 宽带服务商提供了一个叫做DNS域名服务器,并且DNS服务器也有一个域名,当你连上宽带网线时就直接访问的是宽带服务商的域名服务器。
  • 获取到ip地址后返回给本地主机再访问到该IP地址的网站上。


    图片.png
端口号

给确定软件的一个网络数字标识,必须保证唯一性。

图片.png
传输协议

UDP

  • 将数据及源和目的封装成数据包中,不需要建立连接
  • 每个数据报的大小在限制在64k内
  • 因为不需要连接,所以是不可靠的协议
  • 不需要建立连接,速度便很快。
    TCP
  • 建立连接,形成传输数据的通道
  • 在连接中进行大数据量的传输
  • 通过三次握手完成连接,是可靠协议
  • 必须建立连接,效率会稍低。

socket通信

  • Socket就是为网络服务提供的一种机制
  • 通信的两端都有Socket :server client
  • 网络通信其实就是Socket间的通信
  • 数据在两个Socket间通过IO传输
图片.png

UDP的发送端

package udp_socket;

import java.io.IOException;
import java.net.*;
/**
 * 通过查阅文档,了解到用于UDP传输协议的对象是DatagramSocket
 * 通过UDP的协议发送一段文本数据
 * 思路:
 * 1.需要将建立UDP的socket,它具备发送或者接收功能。
 * 2.将数据封装到数据包中。数据包对象是DatagramPackage
 * 3.使用socket对象的send方法将数据包发送出去。
 * 4.关闭资源。
 */
public class Udp_Send {
    public static void main(String[] args) throws IOException {

        System.out.println("UDP发送端 run");
        //创建socket对象
        DatagramSocket ds = new DatagramSocket();

        //创建数据资源
        String bytes = "你好呀!123 java111118  98489415481     2854969541";
        byte[] bytes1 = bytes.getBytes();

        DatagramPacket dp = new DatagramPacket(bytes1, bytes.length(), InetAddress.getByName("115.50.18.31"), 10000);

        ds.send(dp);
        ds.close();
    }
}

UDP的接收端

package udp_socket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * 定义一个udp的接收端。接收发送过来的数据。并显示在屏幕上
 * 思路:
 * - 1.先创建udp 的socket服务,并且指定同一端口
 * - 2.接收数据之前先创建数据包成byte数组
 * - 3.定义数据包
 * - 4.通过数据包对象获取数据包的内容,发送端的ip,发送端的端口,发送过来的数据。
 * - 5.将接收端IP 端口号,内容 打印在屏幕上
 * - 6.最后关闭资源。
 */
public class Udp_Receive {
    public static void main(String[] args) throws IOException {

        System.out.println("UDP的接收端 run");

        DatagramSocket ds=new DatagramSocket(10000);


        byte [] bytes=new byte[1024];
        DatagramPacket dat=new DatagramPacket(bytes,bytes.length);

        ds.receive(dat);


        String ip=dat.getAddress().getHostAddress();

        int port=dat.getPort();


        String test=new String(dat.getData(),0,dat.getLength());

        System.out.println(ip+"----"+port+"------"+test);
        //115.50.18.31----61651------你好呀!123 java111118  98489415481     28
        ds.close();

    }
}

键盘录入

  • 使用高效缓冲流对象创建键盘录入对象
    读取字符串后转化为字节数组
  • 循环读取并发送数据
    UDP发送端
package udp_socket2.udp_socket;


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.Buffer;

/**
 * 通过查阅文档,了解到用于UDP传输协议的对象是DatagramSocket
 * 通过UDP的协议发送一段文本数据
 * 思路:
 * 1.需要将建立UDP的socket,它具备发送或者接收功能。
 * 2.将数据封装到数据包中。数据包对象是DatagramPackage
 * 3.使用socket对象的send方法将数据包发送出去。
 * 4.关闭资源。
 */
public class Udp_Send2 {
    public static void main(String[] args) throws IOException {

        System.out.println("UDP发送端 run");
        //创建socket对象
        DatagramSocket ds = new DatagramSocket();

        BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        String line=null;
        while ((line=bf.readLine())!=null){
            if (line.equals("over")) {
                break;
            }
           byte[] bytes=line.getBytes();
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("115.50.18.31"), 10000);
            ds.send(dp);
        }
        ds.close();
    }
}

UDP接收端

package udp_socket2.udp_socket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * 定义一个udp的接收端。接收发送过来的数据。并显示在屏幕上
 * 思路:
 * - 1.先创建udp 的socket服务,并且指定同一端口
 * - 2.接收数据之前先创建数据包成byte数组
 * - 3.定义数据包
 * - 4.通过数据包对象获取数据包的内容,发送端的ip,发送端的端口,发送过来的数据。
 * - 5.将接收端IP 端口号,内容 打印在屏幕上
 * - 6.最后关闭资源。
 */
public class Udp_Receive2 {
    public static void main(String[] args) throws IOException {

        System.out.println("UDP的接收端 run");

        DatagramSocket ds=new DatagramSocket(10000);

while (true) {

    byte[] bytes = new byte[1024];
    DatagramPacket dat = new DatagramPacket(bytes, bytes.length);

    ds.receive(dat);


    String ip = dat.getAddress().getHostAddress();

    int port = dat.getPort();


    String test = new String(dat.getData(), 0, dat.getLength());

    System.out.println(ip + "----" + port + "------" + test);

}
//ds.close();
    }
}

UDP群聊
192.168.1.3
其中的3表示该局域网下的编号为3的主机
如果将3变成255,将会把发送的信息发给该网段的所有0~255(0不是一台主机,255也不包含)内的所有主机。实现了广播操作-----群聊
UDP发送端

package udp_chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * 创建发送端,并实现Runnable接口
 * 并且将socket发送端对象使用构造器传递
 * 实现run()方法,将键盘录入的信息转化为字节数组,然后转化为数据报文包发送
 */
public class Send implements Runnable {
    private DatagramSocket ds;
    private BufferedReader bf = null;

    public Send(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    public void run() {
        try {
            bf = new BufferedReader(new InputStreamReader(System.in));
            String line;
            while ((line = bf.readLine()) != null) {
                byte[] bytes = line.getBytes();
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.1.255"), 10000);
                ds.send(dp);
                if (line.equals("886")) {
                    break;
                }
            }
        } catch (IOException e) {

        }
        ds.close();
    }
}

UDP接收端

package udp_chat;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * 接收端创建线程对象
 * 也将Rece的对象中添加socket通信对象
 * 同样实现run方法
 * 并将数据接受后并打印
 */
public class Rece implements Runnable {
    private DatagramSocket ds;

    public Rece(DatagramSocket ds) {
        this.ds = ds;
    }

    @Override
    public void run() {

        try {
            while (true) {

                byte[] bytes = new byte[1024];
                DatagramPacket da = new DatagramPacket(bytes, bytes.length);

                ds.receive(da);

                String ip = da.getAddress().getHostAddress();

                int port = da.getPort();

                String test = new String(da.getData(), 0, da.getLength());

                System.out.println(ip + "----" + port + "------" + test);
                if (test.equals("886")) {
                    System.out.println(ip + "----退出聊天室");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

群聊测试类

package udp_chat;

import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * UDP实现群聊
 * 思路:
 * 这个操作既有发送,也有接收,需要两个线程
 * 一个负责接收,一个负责发送
 */
public class TestChat {
    public static void main(String[] args) throws SocketException {
        //创建非共享的socket
        DatagramSocket send = new DatagramSocket();
        //接收端需要定义端口
        DatagramSocket rece = new DatagramSocket(10000);

        //实例化发送端
        Send se = new Send(send);
        //实例化接收端
        Rece re = new Rece(rece);

        //创建线程对象
        Thread t1 = new Thread(se);
        Thread t2 = new Thread(re);
        //开启线程
        t1.start();
        t2.start();

    }
}

TCP通信

TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。
两端通信步骤:

    1. 服务端程序,需要事先启动,等待客户端的连接。
    1. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。

两个类用于实现TCP通信程序

  • 1.客户端: java.net.Socket 类表示。创建 Socket 对象,向服务端发出连接请求,服务端响应请求,两者建 立连接开始通信。
    1. 服务端: java.net.ServerSocket 类表示。创建 ServerSocket 对象,相当于开启一个服务,并等待客户端 的连接。

客户端TCP

package tcp_socket;

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

/**
 * 需求:通过tcp传输将数据发送给服务器
 * 思路:
 * 1.建立tcp的客户端socket,明确服务端的地址和端口。
 * 2.如果通道建立成功就会出现socket io流。
 * 客户端需要做的就是获取socket流中的输出流将数据发送给目的服务器端。
 * 3.通过socket输出流将数据发送。
 * 4.关闭资源(只需要关闭socket即可)。
 */
public class SocketClient {
    public static void main(String[] args) throws IOException {

        Socket so=new Socket("192.168.1.3",10005);

        OutputStream out = so.getOutputStream();

        out.write("hello java".getBytes());

        so.close();
    }
}
//Exception in thread "main" java.net.ConnectException: Connection refused: connect
//由于未定义服务器端,连接失败,抛出异常。

TCP服务端

package tcp_socket;

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

/**
 * 需求:获取客户端的数据并显示在屏幕上
 * 思路:
 * 1.创建服务器端的SeverSocket,明确端口,监听一个端口
 * 2.获取socket 对象
 * 3.服务器端只要获取连接过来的客户端就可以与指定的客户端通信了
 * 4.通过获取客户端读取流对象读取客户端发来的数据
 * 5.并显示在屏幕上
 * 6.关闭资源。
 */
public class SocketServerDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("服务器端 run");
        //创建服务器端
        ServerSocket ss=new ServerSocket(10003);
        while(true){
        //获取socket 对象
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+"----------connected");
        //获取客户端的读取流对象
        InputStream in = s.getInputStream();
        //创建字节数组
        byte [] bytes=new byte[1024];
        //读取数据
        int len = in.read(bytes);
        //打印数据
        System.out.println(new String(bytes,0,len));
        //关闭客户端流资源
        s.close();
    }}
}

TCP客户端,服务端通信

  • 客户端
package socket_TCP2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ClientSocketDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("客户端启动......");
        //创建Socket对象,并指定ip地址和端口号
        Socket s=new Socket("192.168.1.3",9999);
        //获取socket的写出流
        OutputStream out=s.getOutputStream();
        //写入数据给服务器
        out.write("服务器,我来了".getBytes());
        //获取服务器返还的数据的读取流对象
        InputStream in = s.getInputStream();
        //数组读取,并打印到屏幕上
        byte [] bytes=new byte[1024];

        int len = in.read(bytes);
        String test=new String(bytes,0,len);
        System.out.println(test);
        //关闭资源
        s.close();
    }
}
  • 服务器端
package socket_TCP2;

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

public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
        System.out.println("服务器端启动......");

        //创建ServerSocket对象,并指定端口号
        ServerSocket ss=new ServerSocket(9999);


        while (true) {
            //持续获取socket对象
            Socket s = ss.accept();
            //打印获取的socket对象的客户端IP地址
            System.out.println(s.getInetAddress().getHostAddress()+"---------connected");
            //获取服务端的读取流对象
            InputStream in = s.getInputStream();

            //读取客户端发来的数据
            byte[] bytes = new byte[1024];

            int len = in.read(bytes);

            System.out.println(new String(bytes, 0, len));

            //将服务端的数据回复给客户端
            OutputStream out = s.getOutputStream();

            out.write("客户端,我已经收到!".getBytes());

            //关闭资源
            s.close();
        }
    }
}

相关文章

网友评论

    本文标题:2019-04-02

    本文链接:https://www.haomeiwen.com/subject/vsuwbqtx.html