探索基础之Java网络通信——第二章

小白的成长来源于努力学习,坚持每天的积累。 ——半杯态

计算机之间的通信,依据于TCP/IP协议簇中的传输层,它分为两种一种是TCP(传输控制协议)和IP(网际协议)。在Java中用Class为ServerSocket类和Socket代表用TCP传输形式,使用DatagramSocket代表使用UDP进行传输。


Socket(也可以叫“套接字”),是两台机器间通信的端点。可以和网卡驱动进行交流。负责把数据交给网卡驱动,或者从网卡驱动中提取数据。

实现网络之间通信分为两种传输方式:TCP,UDP

TCP (可靠,数据流,面向连接)

分客户端(client),服务端(server)两个角色

情景一:实现简单版单机通信方式
提示:可以结合TCP/IP三次握手进行理解

在这里插入图片描述

客户端实现:
package com.banbeitai.io.socket.communication;

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


/*
 * TCP:
 * 	 客户端,主动连接服务器
 *
 * Socket(InetAddress address, int port)
 * Socket(String host, int port)
 *
 * 步骤:
 * 1、连接服务器
 * Socket socket = new Socket("192.168.30.2",9999);
 *
 * 2、发送或接受数据
 *
 * 3、断开连接
 */
public class TestClientVersion1 {

    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("127.0.0.1", 9999);

        byte[] data = new byte[1024];

        InputStream inputStream = socket.getInputStream();
        int len;
        if ((len=inputStream.read(data))!=-1){
            System.out.println(new String(data,0,len));
        }
    }
}
服务端实现:
package com.banbeitai.io.socket.communication;

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


public class TestServerVersion1 {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(9999);

        Socket socket = server.accept();
        System.out.println(socket.getInetAddress() + "客户端连接成功!");

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("欢迎你登录成功".getBytes());
        socket.close();
        server.close();java
    }
}

根据图以及代码可知:

  • 第一步:客户端发送请求到服务端,告知服务端,客户端发送请求是可以的。

  • 第二步: Socket socket = server.accept();这行代码表示服务端进行接收,getOutputStream方法代表是发送,相当于SYN+ACK,代表服务端,接收和发送

  • 第三步:就是客户端接收到服务端的发送的信息,响应可以成功接收指令给服务端

    由此可以建立两个设备间的通信。

情景二:实现短连接的通信

短连接:建立网络通信,两个服务或者设备之间每次都要进行建立连接,造成很大开销,这是HTTP1.0

客户端实现:
package com.banbeitai.io.socket.communication;

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

/**
 * 客户单发送请求,并响应服务端的请求
 */
public class TestClientVersion2 {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 9999);

        OutputStream outputStream = socket.getOutputStream();
        //第一次握手,由客户端进行发送  SYN   目的是确定客户端能够发送消息
        outputStream.write("你好,服务端,我是半杯态".getBytes());

        /**
         *  out.close();//错误的,如果调用out.close()会导致socket的close()
         * 状态处于半开状态,只关闭了输出的通道
         * 调用此方法为了,暂时关闭客户端,如果不关闭,服务端是以为还有消息发送,不会给出响应,处于等待状态
         */
        socket.shutdownOutput();
        //第三次握手,接受到消息并响应,建立网络通信  ACK 目的是告诉客户端可以收到服务端的消息
        System.out.println("客户端收到:");
        InputStream in = socket.getInputStream();
        byte[] data = new byte[1024];
        int len;
        while((len = in.read(data)) != -1){
            System.out.println(new String(data,0,len));
        }
        socket.close();

    }
}
服务端实现:
package com.banbeitai.io.socket.communication;

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

/**
 * 服务端接收客户端的消息,并返回给客户端一个回复,代表链接成功
 * 可以理解为短连接
 */
public class TestServerVersion2 {
    public static void main(String[] args) throws IOException {

        ServerSocket server = new ServerSocket(9999);
        //第二次握手,服务端接受并发送    SYN+ACK  目的是为响应客户端,服务端可以收到信息,并且可以发送消息
        Socket socket = server.accept();
        System.out.println(socket.getInetAddress()+"客户端连接成功");

        InputStream in = socket.getInputStream();

        byte[] data = new byte[1024];
        int len;
        System.out.println("服务器收到:");
        while ((len = in.read(data)) != -1) {
            System.out.println(new String(data,0,len));
        }

        OutputStream outputStream = socket.getOutputStream();

        outputStream.write("欢迎你,半杯态,你登录成功".getBytes());

        socket.close();
        server.close();
    }
}
情景三:实现长连接的通信

长连接:建立网络通信,两个服务或者设备之间可以持续的进行交互,这是HTTP1.1

客户端实现:
package com.banbeitai.io.socket.communication;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class TestClientVersion3 {

    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("127.0.0.1", 9999);

        OutputStream outputStream = socket.getOutputStream();

        PrintStream printStream = new PrintStream(outputStream);

        Scanner input = new Scanner(System.in);
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        while (true) {
            System.out.println("请输入词语:");
            String word = input.next();
            //发送给服务器端
            printStream.println(word);
            if ("bye".equalsIgnoreCase(word)) {
                break;
            }
            String result = br.readLine();

            System.out.println("服务器转换后的数据:"+ result);
        }

        input.close();
        socket.close();

    }
}
服务端实现:
package com.banbeitai.io.socket.communication;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TestServerVersion3 {
    public static void main(String[] args) throws IOException {

        ServerSocket server = new ServerSocket(9999);

        Socket socket = server.accept();

        InputStream inputStream = socket.getInputStream();

        BufferedReader br  = new BufferedReader(new InputStreamReader(inputStream));

        PrintStream ps = new PrintStream(socket.getOutputStream());
        String word;
        while ((word = br.readLine()) != null) {
            if ("bye".equalsIgnoreCase(word)) {
                break;
            }
            StringBuilder sb = new StringBuilder(word);
            sb.reverse();
            ps.println(sb.toString());
        }

        socket.close();

        server.close();
    }

}

UDP(不可靠,数据报文,无连接)

分发送端(Send),接收端(Receive)两个角色

Class DatagramSocket 常用方法:
方法返回值含义
DatagramSocket()构建一个数据报套接字绑定到本地主机的任何可用的端口,
DatagramSocket(int port)构建一个数据报套接字绑定到本地主机的指定端口,
connect(InetAddress address, int port)void将套接字连接到这个套接字的远程地址。
send(DatagramPacket p)void从这个套接字发送数据报包。
DatagramPacket 常用方法:
方法返回值含义
DatagramPacket(byte[] buf, int length)无接收数据包长度 length DatagramPacket构建
getData()byte[]返回数据缓冲区。数据的接收或发送的数据从缓冲区中的 offset,和运行 length长。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)发送有偏置 ioffsetto指定端口号指定主机上的数据包长度 length数据报包结构。
发送端:
package com.banbeitai.io.socket.udp;

import java.io.IOException;
import java.net.*;

public class TestSend {

    public static void main(String[] args) throws IOException {

        DatagramSocket ds = new DatagramSocket();

        //2、准备把要发送的数据打包

        String str = "欢迎半杯态";
        byte[] bytes = str.getBytes();

        InetAddress ip = InetAddress.getByName("127.0.0.1");
        DatagramPacket dp = new DatagramPacket(bytes,0,bytes.length, ip, 9999);

        ds.send(dp);
        System.out.println("发送完毕");
        ds.close();
    }
}

接收端:
package com.banbeitai.io.socket.udp;

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


public class TestReceive {

    public static void main(String[] args) throws IOException {

        DatagramSocket ds = new DatagramSocket(9999);

        //2、准备一个数据报,接收数据
        byte[] data = new byte[1024];
        DatagramPacket dp = new DatagramPacket(data,data.length);

        ds.receive(dp);

        byte[] dpData = dp.getData();
     //   int len = dp.getLength();
        System.out.println(new String(dpData,0,dp.getLength()));

        ds.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值