参考链接:简单理解Socket – 谦行 – 博客园

简单的一对一Socket通信_翻身了,咸鱼!-CSDN博客

一、Tcp/Ip

先回顾一下TCP/IP协议

TCP/IP协议是指因特网整个TCP/IP协议族。不同于ISO模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中

应用层:TFTP,HTTP(面向连接),SNMP,FTP,SMTP,DNS,Telnet 等等

传输层:TCP(安全可靠,面向连接,无差错传输),UDP(不可靠的,面向无连接的,传输数据过程中数据可能会丢失,不自动重发看电影 )

网络层(也称为网际层,实现端到端数据分组传输,采用无连接交换方式完成 ):IP,ICMP,OSPF,EIGRP,IGMP

网络接口层:

二、Socket是什么?

我们知道IP层的ip地址可以唯一标识主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。能够唯一标示网络中的进程后,它们就可以利用socket进行通信了

Socket(就是套接字)是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。

套接字用来描述ip地址和端口号,Socket=(IP地址:端口号),套接字的表示方法是点分十进制的lP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。例如:如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)

 三、服务器端

第一步:创建一个服务器端,执行ServerSocket.accept()方法,等待客户端连接

 第二步:获取客户端传输过来的字节流(socket.getInputStream()),InputStreamReader将字节流转换为字符流,BufferReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取,利用bufferReader.readLine()方法循环读取数据

第三步:获取客户端的输出流(socket.getOutputStream()),printWriter.write(str)str是回应给客户端的内容,printWriter.flush(),清空缓存区

第四步:关闭资源

package socket;

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

/**
 * @Description:服务器端
 */
public class Server {
    public static void main( String[] args ) throws IOException {
        //第一步:创建一个服务器端,并等待连接客户端
        //创造一个服务器端,端口号为81
        ServerSocket server=new ServerSocket(8888);
        System.out.println("服务器端已启动***************************");
        //调用ServerSocket的accept()方法等待连接,该方法会使线程阻塞,
        //直到接收到一个客户端的连接
        Socket socket= server.accept();

        //第二步:获得客户端传过来的信息

        //获取客户端传输过来的字节流
        InputStream inputStream = socket.getInputStream();

        //InputStreamReader 将字节流转换为字符流
        //是字节流通向字符流的桥梁,封裝了InputStream在里头, 它以较高级的方式,一次读取一个一个字符,以文本格式输入 / 输出,可以指定编码格式;
        InputStreamReader reader = new InputStreamReader(inputStream);

        //从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
        BufferedReader bufferedReader = new BufferedReader(reader);

        //BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,而且提供了很实用的readLine,
        // 读取一个文本行,从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。

        String info=null;
        //利用bufferReader.readLine()方法循环读取数据
        while((info=bufferedReader.readLine())!=null)
        {
            System.out.println("客户端说:"+info);
        }
        /*虽然在大多数的时候可以直接使用Socket类或输入输出流的close方法关闭网络连接
        ,但有时我们只希望关闭OutputStream或InputStream,而在关闭输入输出流的同时,并不关闭网络连接。
        这就需要用到Socket类的另外两个方法:shutdownInput和shutdownOutput,
        这两个方法只关闭相应的输入、输出流,而它们并没有同时关闭网络连接的功能。
        和isClosed、isConnected方法一样,Socket类也提供了两个方法来判断Socket对象的输入、输出流是否被关闭,
        这两个方法是isInputShutdown()和isOutputShutdown()。*/
        socket.shutdownInput();

        //第三步:获取客户端的输出流,回应给客户
        OutputStream outputStream = socket.getOutputStream();
      //  具有自动行刷新的缓冲字符输出流,特点是可以按行写出字符串,并且可以自动行刷新。
        PrintWriter printWriter = new PrintWriter(outputStream);
//控制台输入内容
        Scanner sc = new Scanner(System.in);
        printWriter.write(sc.next());
        printWriter.flush();

//第四步:关闭资源
        printWriter.close();
        outputStream.close();
        bufferedReader.close();
        reader.close();
        inputStream.close();

        socket.close();
        server.close();
    }
}

四、客户端

第一步:创建Socket客户端,指定服务器地址(此处是本机地址)和端口

第二步:与服务器端连接成功后,给服务器端发送信息

第三步:获取输入流得到服务器端的消息

第四步:关闭资源

package socket;

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

public class Client {
    public static void main(String[] args)throws Exception {

        //1.创建Socket客户端,指定服务器地址(此处是本机地址)和端口
        Socket socket=new Socket("127.0.0.1",8888);
        System.out.println("这是客户端*********");

        //2.连接成功后发送信息
        //获取输出流
        OutputStream outputStream=socket.getOutputStream();
        PrintWriter out=new PrintWriter(outputStream);
       Scanner sc= new Scanner(System.in);
        out.write(sc.next());
        out.flush();

//这一句很重要,要写在前面,如果不写在这里,Socket Server 端的代码就会卡在读取inputStream中
        socket.shutdownOutput();

        //3.获取输入流得到服务器端的响应
        InputStream inputStream= socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(inputStream);
        BufferedReader br=new BufferedReader(isr);

        String  info=null;
        while((info=br.readLine())!=null){//循环读取信息
            System.out.println("收到服务端的响应:"+info);
        }


        br.close();
        isr.close();
        out.close();

        out.close();
        socket.close();


    }
}

五、运行效果

启动server端和client端之后,在客户端输入hello,服务器端回复hi

六、总结

Socket通信的server端和Client端交互过程如图所示:

例子中只能实现服务器端和客户端互相发送一条消息,如果想相互交互多条消息,在客户端将 与服务端相互通信的语句加个while循环就好。


版权声明:本文为m0_59181747原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_59181747/article/details/121108750