网络通讯协议,UDP通讯,TCP通讯

 

1    网络通讯协议

经过计算机网络可使多台计算机实现链接,位于同一个网络中的计算机在进行链接和通讯时须要遵照必定的规则数组

1.1     IP地址和端口号

1.计算机指定一个标识号,经过这个标识号来指定接受数据的计算机或者发送数据的计算机。服务器

2.IPv4,它是由4个字节大小的二进制数来表示,如:00001010000000000000000000000001。因为二进制形式表示的IP地址很是不便记忆和处理,所以一般会将IP地址写成十进制的形式,每一个字节用一个十进制数字(0-255)表示,数字间用符号“.”分开,如 “192.168.1.100”。网络

3.IPv6使用16个字节表示IP地址,它所拥有的地址容量约是IPv4的8×1028倍,达到2128个(算上全零的),这样就解决了网络地址资源数量不够的问题。oracle

4.访问目标计算机中的某个应用程序,还须要指定端口号。在计算机中,不一样的应用程序是经过端口号区分的。端口号是用两个字节(16位的二进制数)表示的,它的取值范围是0~65535,其中,0~1023之间的端口号用于一些知名的网络服务和应用,用户的普通应用程序须要使用1024以上的端口号,从而避免端口号被另一个应用或服务所占用dom

1.2     InetAddress

public class Demo01 { public static void main(String[] args) throws UnknownHostException { //获取本地主机对象
        InetAddress inet=InetAddress.getLocalHost(); System.out.println(inet); //根据主机名获取Inet对象
        InetAddress inet2=InetAddress.getByName("PC-201704301608"); System.out.println(inet2); //获取主机名
 System.out.println(inet2.getHostName()); //获取ip地址
        String ip=inet.getHostAddress(); System.out.println(ip); } }

2    UDP与TCP协议

2.1  UDP是无链接通讯协议,即在数据传输时,数据的发送端和接收端不创建逻辑链接。socket

UDP传输数据被限制在64K之内this

2.2  TCP协议是面向链接的通讯协议,即在传输数据前先在发送端和接收端创建逻辑链接,而后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。spa

“三次握手”:第一次握手,客户端向服务器端发出链接请求,等待服务器确认,第二次握手,服务器端向客户端回送一个响应,通知客户端收到了链接请求,第三次握手,客户端再次向服务器端发送确认信息,确认链接。计算机网络

3  UDP通讯

JDK中提供了一个DatagramPacket类,该类的实例对象就至关于一个集装箱,用于封装UDP通讯中发送或者接收的数据。线程

在建立发送端和接收端的DatagramPacket对象时,使用的构造方法有所不一样,接收端的构造方法只须要接收一个字节数组来存放接收到的数据,而发送端的构造方法不但要接收存放了发送数据的字节数组,还须要指定发送端IP地址和端口号。

JDK中提供的一个DatagramSocket类。DatagramSocket类的做用就相似于码头,使用这个类的实例对象就能够发送和接收DatagramPacket数据包。

发送端:

public class UDPSend { //UDP协议发送端
    public static void main(String[] args) throws IOException { Scanner sc=new Scanner(System.in); String str=sc.next(); //1.建立数据包对象,封装要发送的信息,接收端的ip以及端口号
        byte[]bytes=str.getBytes(); InetAddress inet=InetAddress.getByName("127.0.0.1"); DatagramPacket dp=new DatagramPacket(bytes, bytes.length,inet,8888); //2.建立DatagramSocket对象
        DatagramSocket ds=new DatagramSocket(); //3.发送数据包
 ds.send(dp); //4.释放资源
 ds.close(); } }

接受端:

public class UDPRecieve { //UDP接收端
    public static void main(String[] args) throws IOException { //1.建立DatagramSocket对象明确端口号
        DatagramSocket ds=new DatagramSocket(8888); //2.建立字节数组接受数据
        byte[]bytes=new byte[1024]; //3.建立数据包对象
        DatagramPacket dp=new DatagramPacket(bytes, bytes.length); //4.接受数据包
 ds.receive(dp); //5.拆包 //获取发送端的ip地址
        String ip=dp.getAddress().getHostAddress(); //获取发送端的端口号
        int port=dp.getPort(); //获取实际数据的长度
        int length=dp.getLength(); System.out.println("ip地址为"+ip+",端口号为"+port+"发送的内容为:"+new String(bytes,0,length)); System.out.println(new String(bytes)); //6.关闭资源
 } }

4   TCP通讯

在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端。

经过一张图来描述服务器端和客户端的数据传输,以下图所示。

服务器端:

 

public class TCPServer { public static void main(String[] args) throws IOException { //建立ServerSocket对象,接受客户端
        ServerSocket server=new ServerSocket(8888); //调用accept方法,获取链接个人客户端的Socket对象
        Socket socket=server.accept(); //获取输入字节流
        InputStream in=socket.getInputStream(); byte[]bytes=new byte[1024]; int len=in.read(bytes); //获取ip地址
        String ip=socket.getLocalAddress().getHostAddress(); //获取端口号
        int port=socket.getPort(); System.out.println(ip+port+new String(bytes,0,len)); //回复客户端
        OutputStream out=socket.getOutputStream(); out.write("收到!".getBytes()); //释放资源
 server.close(); } }

客户端:

public class TCPClient { public static void main(String[] args) throws IOException { // 建立Socket对象,链接服务器
        Socket socket = new Socket("127.0.0.1", 8888); // 获取字节输出流
        OutputStream out = socket.getOutputStream(); // 发送数据
        out.write("你好服务器".getBytes()); // 接受服务器端的回复
        InputStream in = socket.getInputStream(); byte[] bytes = new byte[1024]; int len = in.read(bytes); // 获取ip地址
        String ip = socket.getLocalAddress().getHostAddress(); // 获取端口号
        int port = socket.getPort(); System.out.println(ip + port + new String(bytes, 0, len)); // 释放资源
 socket.close(); } }

练习:文件上传到服务器

线程接口:

public class MyRunnable implements Runnable { private Socket socket; public MyRunnable(Socket socket) { this.socket = socket; } public void run() { FileOutputStream fos = null; try { // 获取字节输入流
            InputStream in = socket.getInputStream(); // 明确目的地
            File file = new File("D:\\upload"); // 若是文件夹不存在,则建立一个新的文件夹
            if (!file.exists()) { file.mkdirs(); } // 文件路径 // 文件名:域名+毫秒值+6位随机数
            String filename = "oracle" + System.currentTimeMillis() + new Random().nextInt(999999); String path = file.getAbsolutePath() + File.separator + filename + ".png"; fos = new FileOutputStream(path); // 开始复制
            byte[] bytes = new byte[1024]; int len = 0; while ((len = in.read(bytes)) != -1) { fos.write(bytes, 0, len); } // 回复客户端
            OutputStream out = socket.getOutputStream(); out.write("上传成功!".getBytes()); } catch (IOException ex) { ex.printStackTrace(); } finally { // 释放资源
            try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } } } }

 

服务器端:

public class TCPServer { public static void main(String[] args) throws IOException { // 建立ServerSocket对象,接受客户端
        ServerSocket server = new ServerSocket(8888); while (true) { // 调用accept方法,建立链接并获取客户端Socket对象
            Socket socket = server.accept(); MyRunnable mr = new MyRunnable(socket); new Thread(mr).start(); } } }

客户端:

public class TCPClient { public static void main(String[] args) throws UnknownHostException, IOException { //建立Socket对象,链接服务器
        Socket socket=new Socket("192.168.1.171",8888); //获取字节输出流
        OutputStream out=socket.getOutputStream(); //建立字节输入流,明确数据源
        FileInputStream fis=new FileInputStream("D:\\test\\a1.jpg"); byte[]bytes=new byte[1024]; //开始复制
        int len=0; while((len=fis.read(bytes))!=-1){ out.write(bytes,0,len); } //告诉服务器端不要再等了,末尾加个标记
 socket.shutdownOutput(); //接受服务器的回复
        InputStream in=socket.getInputStream(); len=in.read(bytes); System.out.println(new String(bytes,0,len)); //释放资源
 fis.close(); socket.close(); } }
相关文章
相关标签/搜索