网络编程

网络编程三要素
    1、IP地址
        要让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。
        Java提供了InetAddress类来获取和操作IP地址。
        网络中计算机的唯一标识。
        计算机只能识别二进制的数据,所以IP地址应该是一个二进制数据。我们配置的IP地址不是二进制的,为了方便表示IP地址,把IP地址的每一个字节上的二进制转换为十进制,术语“点分十进制”。
        IP地址的组成:网络号段 + 主机号段
        IP地址的分类:
            A:第一号段为网络号段 + 后三段的主机号段
                一个网络号: 256 * 256 * 256
            B: 前二号段为网络号段 + 后二段的主机号段
                一个网络号: 256 * 256
            C: 前三号段为网络号段 + 后一段的主机号段
                一个网络号: 256
                192.168.x.x是私有地址
        DOS:
            ipconfig 查看本机ip地址
            ping 后面跟ip地址,测试本机与指定ip地址间的通信是否正常。
        特殊IP:127.0.0.1(表示本机)
                x.x.x.255 广播地址,不建议使用
                x.x.x.0 网络地址,不建议使用

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

public class InetAddressDemo {

    public static void main(String[] args) throws UnknownHostException {
        //static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。 根据主机名和IP地址的字符串表示得到IP地址对象。
        //InetAddress ia = InetAddress.getByName("MAYBE");
        //传入IP地址或主机名都可以
        InetAddress ia = InetAddress.getByName("192.168.181.1");
        // String getHostName()  获取此 IP 地址的主机名。  主机名
        String name = ia.getHostName();
        // String getHostAddress()返回 IP 地址字符串(以文本表现形式)。  IP地址
        String address = ia.getHostAddress();
        System.out.println("name:  " + name);
        System.out.println("address:  " + address);
    }

}

    2、端口
        物理端口网卡口
        逻辑端口 我们指的是逻辑端口
            A: 每个网络程序都会至少有一个逻辑端口
            B:用于标识进程的逻辑地址,不同进程的标识
            C:有效端口:0——65535,其中0——1024系统使用或保留端口。
    3、协议
        通信规则
        UDP
            将数据源和目的地封装成数据包中,不需要建立连接,每个数据包的大小限制在64k;因无连接,是不可靠协议;不需要建立连接,不可靠。
        TCP
            建立连接,形成传输数据的通道;在连接中进行大数据量传输了通过三次握手完成连接,是可靠协议,必须建立连接,效率低。

Socket套接字
    网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
    原理机制:
        1、通信的两端都有Socket;
        2、网络通信其实就是Socket间的通信;
        3、数据在两个Socket间通过IO传输。

  UDP接收发送

//接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/*
 * 接收UDP,接收端要先运行
 * 类 DatagramSocket  void receive(DatagramPacket p)  从此套接字接收数据报包。 
 * 类 DatagramPacket  
 *     A:创建Socket对象 DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。
 *     B:创建一个数据包(接收容器) DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。
 *     C:调用Scoket对象接收数据
 *     D:解析数据包 byte[] getData() 返回数据缓冲区 
 *             int getLength()  返回将要发送或接收到的数据的长度。获取实际长度 
 *     E:释放资源
 * */
public class UDPSocket2 {
    public static void main(String[] args) throws IOException {

        // DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,将其绑定到指定的本地地址。
        //创建接收端对象,本机只需指定端口号。
        DatagramSocket ds = new DatagramSocket(10086);
        
        //每次要读的数据包
        byte[] b = new byte[1024];
        int length = b.length;
        //创建接收数据包 
        //DatagramPacket(byte[] buf, int length) 构造 DatagramPacket,用来接收长度为 length 的数据包。
        DatagramPacket dp = new DatagramPacket(b, length);
        
        //接收数据
        ds.receive(dp);
        
        //解析接收到的数据包
     //String s = new String(dp.getData(), 0, dp.getData().length);
byte[] ReceiveB = dp.getData(); int len = ReceiveB.length; String s = new String(ReceiveB, 0, len); //System.out.println(s); ds.close(); } } //---------------------------------------------------- //发送端 import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* * UDP协议发送协议 * 1、首先创建发送端对象 * 2、创建数据并把数据打包 * 3、调用Socket发送方法发送数据包 * 4、释放资源 * * */ public class UDPSocket1 { public static void main(String[] args) throws IOException { //创建对象,UDP使用DatagramSocket这个类 DatagramSocket ds = new DatagramSocket(); //创建数据并打包,长度为 length 的包发送到指定主机上的指定端口号。 //设置IP地址 InetAddress ia = InetAddress.getByName("192.168.181.1"); //要发送的数据 byte[] b = "hello,UDP".getBytes(); int length = b.length; // DatagramPacket(byte[] buf, int length, InetAddress address, int port) 数据包、数据包大小、IP地址、端口号 DatagramPacket dp = new DatagramPacket(b, length, ia, 10086); //发送数据包 ds.send(dp); //发送数据包 void send(DatagramPacket p) 从此套接字发送数据报包。 //释放资源 ds.close(); } }

  接收端相当于服务器,应该一直开着,不关闭。

  多线程UDP

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

public class ReceiveThread implements Runnable {
    private DatagramSocket ds;

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

    @Override
    public void run() {
        try {
            while (true) {
                // 创建一个包裹
                byte[] bys = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bys, bys.length);

                // 接收数据
                ds.receive(dp);

                // 解析数据
                String ip = dp.getAddress().getHostAddress();
                String s = new String(dp.getData(), 0, dp.getLength());
                System.out.println("from " + ip + " data is : " + s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

public class SendThread implements Runnable {

    private DatagramSocket ds;

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

    @Override
    public void run() {
        try {
            // 封装键盘录入数据
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    System.in));
            String line = null;
            while ((line = br.readLine()) != null) {
                if ("886".equals(line)) {
                    break;
                }

                // 创建数据并打包
                byte[] bys = line.getBytes();
                // DatagramPacket dp = new DatagramPacket(bys, bys.length,
                // InetAddress.getByName("192.168.12.92"), 12345);
                DatagramPacket dp = new DatagramPacket(bys, bys.length,
                        InetAddress.getByName("192.168.12.255"), 12306);

                // 发送数据
                ds.send(dp);
            }

            // 释放资源
            ds.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

/*
 * 通过多线程改进刚才的聊天程序,这样我就可以实现在一个窗口发送和接收数据了
 */
public class ChatRoom {
    public static void main(String[] args) throws IOException {
        DatagramSocket dsSend = new DatagramSocket();
        DatagramSocket dsReceive = new DatagramSocket(12306);

        SendThread st = new SendThread(dsSend);
        ReceiveThread rt = new ReceiveThread(dsReceive);

        Thread t1 = new Thread(st);
        Thread t2 = new Thread(rt);

        t1.start();
        t2.start();
    }
}
TCP发送数据的步骤:    
    A:创建发送端Socket对象
        类 Socket 
            Socket(InetAddress address, int port)创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
            Socket(String host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号。
          创建一个流套接字并将其连接到指定主机上的指定端口号。
        这一步如果成功,就说明已经连接成功
    B:获取输出流写数据
        OutputStream getOutputStream() 返回此套接字的输出流。 
    C:释放资源
TCP协议一定要先开服务器,一定会保证数据被收到,所以接收端一定要被开启。
TCP接收:
        A:创建接收端Socket对象(服务器端的Socket对象ServerSocket)
            ServerSocket(int port) 创建绑定到特定端口的服务器套接字。
        B:监听客户端连接,返回对应的Socket对象
            Socket accept()侦听并接受到此套接字的连接。 
        C:获取输入流,读取数据
            InputStream getInputStream() 
          返回此套接字的输入流。 返回此套接字的输入流。
        D:释放资源


       

原文地址:https://www.cnblogs.com/changzuidaerguai/p/6901531.html