java网络编程基础

InetAddress

首先介绍一个api : InetAdderss,该类用于封装一个IP地址,并且提供了一系列的IP地址相关操作的方法

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

/*
 * InetAddress:此类表示互联网协议 (IP) 地址。 
 * 
 */
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException   {
        //方法:static InetAddress getByName(String host)

        //InetAddress address = InetAddress.getByName("hostname");
        InetAddress address = InetAddress.getByName("192.168.1.107");//ip地址是唯一的

        //System.out.println(address);//hostname/192.168.1.107 ipconfig

        String hostAddress = address.getHostAddress();//192.168.1.107 返回IP地址
        String hostName = address.getHostName();//hostname 返回主机名

        System.out.println(hostAddress);
        System.out.println(hostName);


    }
}

UDP协议

UDP协议:
    UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。
简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,
就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
    由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,
因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,
不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。

DatagramPacket

UDP通信的过程就像是货运公司在两个码头间发送货物一样。在码头发送和接收货物时都需要使用集装箱来装载货物,UDP通信也是一样,发送和接收的数据也需要使用“集装箱”进行打包,为此JDK中提供了一个DatagramPacket(详细参考API)类,该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据。

DatagramSocket

DatagramPacket(详细参考API)数据包的作用就如同是“集装箱”,可以将发送端或者接收端的数据封装起来。然而运输货物只有“集装箱”是不够的,还需要有码头。在程序中需要实现通信只有DatagramPacket数据包也同样不行,为此JDK中提供的一个DatagramSocket类。DatagramSocket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包,发送数据的过程如下图所示。

这里写图片描述

UDP的实现

发送端

代码案例:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/*
 * 使用UDP协议发送数据的步骤
        创建发送端Socket对象
        创建数据并打包
        发送数据
        释放资源
 * 
 * DatagramSocket:此类表示用来发送和接收数据,基于UDP协议的
 * 
 * DatagramSocket() :创建Socket对象并随机分配端口号
 * DatagramSocket(int port) :创建Socket对象并指定端口号
 */
public class SendDemo {
    public static void main(String[] args) throws IOException  {
        //创建发送端Socket对象
        DatagramSocket ds = new DatagramSocket();
        //创建数据并打包
        /*
         * DatagramPacket :此类表示数据报包
         * 数据 byte[]
         * 设备的地址 ip
         * 进程的地址  端口号
           DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
         */

        String s = "hello udp,im comming!";
        byte[] bys = s.getBytes();
        int length = bys.length;
        InetAddress address = InetAddress.getByName("itheima");//发送给当前设备
        int port = 8888;
        //打包
        DatagramPacket dp = new DatagramPacket(bys,length,address,port);
        //发送数据
        ds.send(dp);
        //释放资源
        ds.close();
    }
}

接收端

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

/*
 * 使用UDP协议接收数据
        创建接收端Socket对象
        接收数据
        解析数据
        输出数据
        释放资源

 */
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        //创建接收端Socket对象
        DatagramSocket ds = new DatagramSocket(8888);
        //接收数据
        //DatagramPacket(byte[] buf, int length) 
        byte[] bys = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bys,bys.length);

        System.out.println(1);
        ds.receive(dp);//阻塞方法,直到接受到数据
        System.out.println(2);

        //解析数据
        //InetAddress getAddress() : 获取发送端的IP对象
        InetAddress address = dp.getAddress();
        //byte[] getData()  :获取接收到的数据,也可以直接使用创建包对象时的数组
        byte[] data = dp.getData();
        //int getLength()  :获取具体收到数据的长度
        int length = dp.getLength();



        //输出数据
        System.out.println("sender ---> " + address.getHostAddress());
        //System.out.println(new String(data,0,length));
        System.out.println(new String(bys,0,length));
        //释放资源
        ds.close();

    }
}

TCP协议

TCP通信同UDP通信一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象。
区别在于,UDP中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意地发送数据。
而TCP通信是严格区分客户端与服务器端的,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不可以主动连接客户端,并且服务器端程序需要事先启动,等待客户端的连接。
在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端。
通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务器端发出连接请求,服务器端响应请求,两者建立连接开始通信。

这里不再做ServerSocket和Socket的介绍,详细参考API

TCP协议的实现

客户端

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

/*
 * 使用TCP协议发送数据
        创建发送端Socket对象(创建连接)
        获取输出流对象
        发送数据
        释放资源

    Socket(InetAddress address, int port) 
    Exception in thread "main" java.net.ConnectException: Connection refused: connect

 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建发送端Socket对象(创建连接)
        Socket s = new Socket(InetAddress.getByName("itheima"),10086);
        //获取输出流对象
        OutputStream os = s.getOutputStream();
        //发送数据
        String str = "hello tcp,im comming!!!";
        os.write(str.getBytes());
        //释放资源
        //os.close();
        s.close();
    }
}

服务端

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

/*
 * 使用TCP协议接收数据
        创建接收端Socket对象
        监听(阻塞)
        获取输入流对象
        获取数据
        输出数据
        释放资源

    ServerSocket:接收端,服务端Socket
    ServerSocket(int port) 
    Socket accept() 

 */
public class ServerDemo {
    public static void main(String[] args) throws IOException  {
        //创建接收端Socket对象
        ServerSocket ss = new ServerSocket(10086);
        //监听(阻塞)
        Socket s = ss.accept();
        //获取输入流对象
        InputStream is = s.getInputStream();
        //获取数据
        byte[] bys = new byte[1024];
        int len;//用于存储读到的字节个数
        len = is.read(bys);
        //输出数据
        InetAddress address = s.getInetAddress();
        System.out.println("client ---> " + address.getHostName());
        System.out.println(new String(bys,0,len));
        //释放资源
        s.close();
        //ss.close();
    }
}

需求:使用TCP协议发送数据,并将接收到的数据转换成大写返回

客户端

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

/*
    需求:使用TCP协议发送数据,并将接收到的数据转换成大写返回

    客户端发出数据
    服务端接收数据
    服务端转换数据
    服务端发出数据
    客户端接收数据

 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket对象
        Socket s = new Socket(InetAddress.getByName("itheima"),10010);
        //获取输出流对象
        OutputStream os = s.getOutputStream();
        //发出数据
        os.write("tcp,im comming again!!!".getBytes());


        //获取输入流对象
        InputStream is = s.getInputStream();
        byte[] bys = new byte[1024];
        int len;//用于存储读取到的字节个数
        //接收数据
        len = is.read(bys);
        //输出数据
        System.out.println(new String(bys,0,len));

        //释放资源
        s.close();

    }
}

服务端


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

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务端Socket对象
        ServerSocket ss = new ServerSocket(10010);
        //监听
        Socket s = ss.accept();
        //获取输入流对象
        InputStream is = s.getInputStream();
        //获取数据
        byte[] bys = new byte[1024];
        int len;//用于存储读取到的字节个数
        len = is.read(bys);
        String str = new String(bys,0,len);
        //输出数据
        System.out.println(str);
        //转换数据
        String upperStr = str.toUpperCase();
        //获取输出流对象
        OutputStream os = s.getOutputStream();
        //返回数据(发出数据)
        os.write(upperStr.getBytes());

        //释放资源
        s.close();
        //ss.close();//服务端一般不关闭
    }
}

猜你喜欢

转载自blog.csdn.net/u013772906/article/details/78698587