网络编程学习

网络编程

网络模型概述和图解

A:网络模型概述

​ 计算机网络之间以何种规则进行通信,就是网络模型研究问题。

​ 网络模型一般是指

​ OSI (Open System Interconnection开放系统互连)七层参考模型

​ TCP/IP四层参考模型

​ 主机至网络层(物理层,数据链路层),网络层,传输层,应用层(应用层,表示层,会话层)

网络模型7层概述:
1.物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。
它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0)。
这一层的数据叫做比特。
2. 数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
3. 网络层:主要将从下层接收到的数据进行IP地址(例192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
4. 传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。
主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。
5.会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。
主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
6.表示层:主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够能识别的东西(如图片、声音等)。
7.应用层: 主要是一些终端的应用,比如说FTP(各种文件下载),WEB(IE浏览),QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。

B:画图演示: 网络模型图解

网络编程(网络编程三要素概述)

A:IP地址:InetAddress:网络:网络中设备的标识,不易记忆,可用主机名

B:端口号:用于标识进程的逻辑地址,不同进程的标识

C:传输协议:通讯的规则常见协议:TCP,UDP

网络编程的三要素:

​ IP:为了标识网络中一台计算机的唯一性。

​ IP协议的作用主要有两个,一个是为每一台计算机分配IP地址,另一个是为了确定哪些地址在同一个子网络。

​ 端口:逻辑端口,他其实是每一个使用网卡的程序编号

​ 接下来的问题是,同一台主机上许多程序都需要用到网络,比如,你一边浏览网页,一边与朋友在线聊天。

​ 当一个数据包从互联网发来的时候,你怎末知道,它表示网页的内容,还是表示在线聊天的内容?

​ 也就是说,我们还需要一个参数,表示这个数据包到底供那个程序(进程)使用。

​ 这个参数就叫做”端口“(port),它其实是每一个使用网卡的程序的编号。

​ 每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。

网络 编程(网络编程的三要素之IP概述)

A:IP概述:所谓IP地址就是给每个连接在Internet上的主机分配的32bit地址。点分十进制 4个字节,一个字节8位

B:IP地址的组成

​ IP地址 = 网络地址+主机地址

​ A类IP地址:第一段号码为网络地址,剩下的三段号码为本地计算机的号码

​ B类IP地址:前二段号码为网络地址,剩下的二段号码为本地计算机的号码

​ C类IP地址:前三段号码为网络地址,剩下的一段号码为本地计算机的号码

C::IP地址分类
A类 1.0.0.1—127.255.255.254
(1)10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)
(2)127.X.X.X是保留地址,用做循环测试用的。
B类 128.0.0.1—191.255.255.254 172.16.0.0—172.31.255.255是私有地址。
C类 192.0.0.1—223.255.255.254 192.168.x.x是私有地址
D类 224.0.0.1—239.255.255.254
E类 240.0.0.1—247.255.255.254

D:特殊地址

​ 127.0.0.1回环地址,可用于测试本机的网络是否有问题。ping 127.0.0.1

DOS命令 ipconfig:查看本机IP地址
xxx.xxx.xxx.255 广播地址

IP协议的作用主要有两个,一个是为每一台计算机分配IP地址,另一个是确定哪些地址在同一个子网络。

网络编程(InetAddress类的概述和使用)

//获取主机名的DOS命令:hostname

A:InetAddress类的概述

​ 为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress供我们使用此类表示互联网协议(IP)地址。

B:InetAddress类的常见功能

public static InetAddress getByName(String host)
public String getHostAddress()//获取IP
public String getHostName()//获取主机名
getLocalHost();

C:案例演示: InetAddress类的常见功能
InetAddress inetAddress = InetAddress.getByName(“SHEN-MOU-MOU”) ;
InetAddress inetAddress = InetAddress.getByName(“192.168.3.120”) ;

网络编程(网络编程三要素之端口和协议)

A:端口

​ 物理端口 网卡口

​ 逻辑端口 我们指的就是逻辑端口

​ a:每个网络程序都会有一个逻辑端口

​ b:用于标识进程的逻辑地址,不同进程的标识

​ c:有效端口:065535(两个字节),其中01023系统使用或者保留端口。

​ 端口的解释:

​ 接下来的问题是,同一台主机上有许多程序都需要用到网络,比如,你一边浏览网页,一般与朋友在线聊条天。

​ 当一个数据包从互联网上发过来的时候,你怎末知道,它表示网页的内容,还是表示,在线聊天的内容?

​ 也就是说,我们还需要一个参数,表示这个数据包到底供那个程序(进程)使用。

​ 这个参数就叫做“端口”(port),他其实是每一个使用网卡的程序的编号。

	每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数。

B:协议

​ UDP发短信

​ 将数据源和目的地封装成数据包,不需要建立连接;

​ 每个数据报包的大小在限制在64K;

​ 因无连接,是不可靠协议;

​ TCP 打电话 视频

​ 建立连接,形成传输数据的通道;

​ 在连接中进行大数据量传输;

​ 需要连接所以是可靠协议;

​ 必须建立连接,效率会稍低

Socket=IP+端口号

​ A:Socket套接字概述:

​ 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识套接字。

​ B:Socket原理机制:

​ 通信两端都有Socket.

​ 网络通信其实就是Socket间的通信。

​ 数据在两个Socket间通过IO传输。

网络编程(UDP协议发送数据)

A:案例演示:	UDP协议发送数据(DatagramSocket)
- 步骤:
- a: 创建UDP通讯客户端对象(DatagramSocket)
- b: 创建数据报包 public DatagramPacket(byte[] buf, int length, InetAddress address,int port)
- c: 发送 数据
- d: 释放资源
public class UDPClient {
   public static void main(String[] args) throws IOException {
        // DatagramSocket()
        // 构造数据报套接字并将其绑定到本地主机上任何可用的端口。
        //创建 客户端的套接字
        DatagramSocket socket = new DatagramSocket();

        //发送数据
        // void send (DatagramPacket p)
        // 从此套接字发送数据报包。DatagramPacket 数据报包用来实现无连接包投递服务。
        // 每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。
        // 从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。

       /* DatagramPacket( byte[] buf, int length, InetAddress address,int port)
        构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。*/
        //创建数据报包
        byte[] bytes = "你好UDP我来了,爱生活,爱Java".getBytes();
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.15.100"), 8888);
        socket.send(packet);

        //关闭客户端,释放资源。
        socket.close();
    }
}

网络编程(UDP协议接收数据)

A:案例演示:	UDP协议接收数据
- 步骤:// public DatagramSocket(int port)
- a: 创建UDP通讯协议服务器端对象(DatagramSocket) 注意要用有参数构造 指定端口号
- b: 创建数据报包,作用用来接收数据  // public DatagramPacket(byte[] buf, int length)
- c: 接收数据  receive(dp) ;
- d: 解析数据报包,拿出数据  dp.getData() ;  dp.getLength() ;
- e: 释放资源
public class UDPServer {
    public static void main(String[] args) throws IOException {
        //类 DatagramSocket 此类表示用来发送和接收数据报包的套接字。
        // DatagramSocket( int port)创建数据报套接字并将其绑定到本地主机上的指定端口。
        //创建服务端的Socket ,并暴露端口号
        DatagramSocket socket = new DatagramSocket(8888);
        //接收数据
        // void receive (DatagramPacket p)从此套接字接收数据报包。
        // DatagramPacket( byte[] buf, int length)
        // 构造 DatagramPacket,用来接收长度为 length 的数据包。
        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
        //receive()方法,接收数据报包,是一个阻塞式方法,等待接收数据
        // 从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。
        // 此方法在接收到数据报前一直阻塞
        System.out.println("服务器已经开启....");
        socket.receive(packet);
        //取出数据报包中的数据
        byte[] data = packet.getData();
        //获取数据的实际长度
        int length = packet.getLength();
        //获取客户端的ip
        InetAddress address = packet.getAddress();
        String ip = address.getHostAddress();
        String s = new String(data, 0, length);
        System.out.println("ip:" + ip + " 给你发来消息:" + s);
        socket.close();
    }
}

网络编程(UDP协议发送端的数据来自于键盘录入)

A:案例演示:	UDP协议发送端的数据来自于键盘录入
B:DOS窗口演示:	开启两个DOS窗口,分别演示发送端和接受端
public class MyClient {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.println("请输入消息");
            String msg = reader.readLine();

            byte[] bytes = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.15.100"), 6666);
            datagramSocket.send(packet);
            if ("886".equals(msg)) {
                break;
            }
        }
        datagramSocket.close();
    }
}
public class MyServer {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(6666);
        System.out.println("服务器已经开启,等待接收数据......");
        while (true) {
            byte[] bytes = new byte[1024];
            DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
            datagramSocket.receive(datagramPacket);
            byte[] data = datagramPacket.getData();
            int length = datagramPacket.getLength();
            String ip = datagramPacket.getAddress().getHostAddress();
            String msg = new String(data, 0, length);
            System.out.println(ip + ":发来消息:" + msg);
            if ("886".equals("msg")) {
                break;

            }
        }
        datagramSocket.close();
    }
}

网络编程(多线程实现聊天室程序)

A:案例演示:	多线程改进聊天小程序


public class ClientThread extends Thread {
    private DatagramSocket clientSocket;

    public ClientThread(DatagramSocket clientSocket) {

        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                System.out.println("请输入消息");
                String msg = reader.readLine();

                byte[] bytes = msg.getBytes();
                DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.15.100"), 6666);
                clientSocket.send(packet);
                if ("886".equals(msg)) {
                    break;
                }
            }
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}



public class MyClient {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.println("请输入消息");
            String msg = reader.readLine();

            byte[] bytes = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.15.100"), 6666);
            datagramSocket.send(packet);
            if ("886".equals(msg)) {
                break;
            }
        }
        datagramSocket.close();
    }
}



public class MyServer {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(6666);

    }
}


public class MyTest {
    public static void main(String[] args) throws SocketException {
        DatagramSocket clientSocket = new DatagramSocket();
        DatagramSocket serverSocket = new DatagramSocket(6666);
        ServerThread serverThread = new ServerThread(serverSocket);
        ClientThread clientThread = new ClientThread(clientSocket);
        serverThread.start();
        clientThread.start();
    }
}


public class ServerThread extends Thread {
    private DatagramSocket serverSocket;

    public ServerThread(DatagramSocket serverSocket) {

        this.serverSocket = serverSocket;
    }

    @Override
    public void run() {
        try {
            System.out.println("服务器已经开启,等待接收数据......");
            while (true) {
                byte[] bytes = new byte[1024];
                DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
                serverSocket.receive(datagramPacket);
                byte[] data = datagramPacket.getData();
                int length = datagramPacket.getLength();
                String ip = datagramPacket.getAddress().getHostAddress();
                String msg = new String(data, 0, length);
                System.out.println(ip + ":发来消息:" + msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


网络编程(TCP协议发送数据)

A:案例演示:	TCP协议发送数据(Scoket)

* 步骤:
- a: 创建TCP通讯协议客户端对象(Socket)   // public Socket(String host, int port)
- b: 获取输出流对象
- c: 写数据
- d: 释放资源


public class TCPServer {
    public static void main(String[] args) throws IOException {
        //ServerSocket此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果
        //创建服务端的Socket,并暴露端口号
        //Exception in thread "main" java.net.BindException: Address already in use: JVM_Bind 端口被占用的异常
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器已经开启等待连接,,,,");
        //侦听客户端的连接,返回客户端scoket
        //侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
        Socket socket = serverSocket.accept(); //阻塞式方法,侦听客户端的连接。
        //获取客户端的ip
        String ip = socket.getInetAddress().getHostAddress();
        //获取通道中的输入流
        InputStream in = socket.getInputStream();
        //读取客户端发过来的数据
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println("ip: " + ip + "给我发来消息:" + s);

        serverSocket.close();

    }
}

网络编程(TCP协议接收数据)(掌握)

A:案例演示:	TCP协议接收数据(ServerSocket)
* 步骤:
- a: 创建TCP通讯协议服务器端对象(ServerSocket)
- b: 监听客户端
- c: 获取输入流对象
- d: 读取数据
- e: 释放资源

public class TCPClient {
    public static void main(String[] args) throws IOException {
        // Socket(String host, int port)
        // 创建一个流套接字并将其连接到指定主机上的指定端口号。

        // Socket(InetAddress address, int port)
        // 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
        //创建 客户端的套接字,参数就是,服务器的ip和端口
        Socket socket = new Socket("192.168.15.100", 9999);
        //获取通道中的输出流
        OutputStream outputStream = socket.getOutputStream();
        //写出数据
        outputStream.write("你好TCP我来了".getBytes());

        socket.close();
    }
}

网络编程(服务器给客户端一个反馈)(掌握)

A:案例演示:	客户端发送数据,服务器接受数据并给出反馈

客户端发完数据 接收服务的反馈

public class MyTCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.15.100", 4444);
        OutputStream out = socket.getOutputStream();
        out.write("你服务器!".getBytes());

        //读取服务的返回
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println("服务端给你发来消息:" + s);
        out.close();
    }
}

public class MyTCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(4444);
        System.out.println("服务器已经开启,,,,");
        Socket socket = serverSocket.accept();
        //获取客户端的ip
        String ip = socket.getInetAddress().getHostAddress();
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println(ip + " 给你发来消息:" + s);

        //反馈客户端
        OutputStream out = socket.getOutputStream();
        out.write("你好客户端".getBytes());


        serverSocket.close();
    }
}


网络编程(客户端键盘录入服务器控制台输出)(掌握)

A:案例演示:	客户端键盘录入服务器控制台输出
public class TCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.15.100", 8888);
        OutputStream out = socket.getOutputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        //把通道中的字节流,包装成字符流
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
        String s = null;
        while (true) {
            System.out.println("请输入消息");
            s = reader.readLine();
            writer.write(s);
            writer.newLine();
            writer.flush();
            if ("886".equals(s)) {
                break;
            }
        }
        socket.close();
    }
}

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务器已经开启,等待连接....");
        Socket sk = serverSocket.accept();
        InputStream in = sk.getInputStream();
        //把通道中的字节流,包装成字符流
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        while (true) {
            String s = reader.readLine();
            System.out.println(s);
            if ("886".equals(s)) {
                break;
            }

        }

        serverSocket.close();

    }
}


网络编程(客户端键盘录入服务器写到文本文件)(掌握)

A:案例演示:	客户端键盘录入服务器写到文本文件
public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接.....");
        Socket sk = serverSocket.accept();
        InputStream in = sk.getInputStream();
        //包装通道中的输入流
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line = null;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        serverSocket.close();
    }
}

网络编程(客户端读取文本文件服务器控制台输出)(掌握)

A:案例演示:	客户端读取文本文件服务器控制台输出

public class TCPClient {
    public static void main(String[] args) throws IOException {
        //客户端读取文本文件服务器控制台输出
        Socket socket = new Socket("192.168.15.100", 6666);
        OutputStream out = socket.getOutputStream();
        //包装通道中的流
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
        BufferedReader reader = new BufferedReader(new FileReader("MyTest.txt"));
        String line = null;
        while ((line = reader.readLine()) != null) {
            writer.write(line);
            writer.newLine();
            writer.flush();
        }
        reader.close();
        socket.close();
    }
}

网络编程(TCP协议上传文本文件)(掌握)

A:案例演示:	TCP协议上传文本文件(客户端读取文本文件发送数据到服务器端,服务器端读取数据存储到文本文件中)

需求: 上传文本文件

public class TCPClient {
    public static void main(String[] args) throws IOException {
        //客户端读取文本文件服务器控制台输出
        Socket socket = new Socket("192.168.15.100", 6666);
        OutputStream out = socket.getOutputStream();
        //包装通道中的流
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
        BufferedReader reader = new BufferedReader(new FileReader("MyTest.txt"));
        String line = null;
        while ((line = reader.readLine()) != null) {
            writer.write(line);
            writer.newLine();
            writer.flush();
        }
        //下来了,给服务端,手写一个标记,告诉服务端,文件数据传完了
     /*   writer.write("over");
        writer.newLine();
        writer.flush();*/
        /*我们手写一个标记,当然可以,但是要确保,你这个标记,在你上传的文件中不要出现*/
        //另外一个解决方案,你的意思就是想要告诉服务端,我这边传完了,不要让服务端等待了
      /*  void shutdownInput ()
        此套接字的输入流置于“流的末尾”。
        void shutdownOutput ()
        禁用此套接字的输出流。*/
        socket.shutdownOutput();

        //客户端 读取服务端的反馈
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println(s);


        reader.close();
        socket.close();
    }
}

网络编程(TCP上传文本文件并给出反馈)(掌握)

A:案例演示:	TCP上传文本文件并给出反馈
B:TCP传输容易出现的问题
	客户端连接上服务端,两端都在等待,没有任何数据传输。
	
	通过例程分析:
		因为read方法或者readLine方法是阻塞式。
	
	解决办法:
		1.自定义结束标记
	解决办法2:使用shutdownInput,shutdownOutput方法。
		//客户端上传文件结束后 直接结束流对象
	// public void shutdownOutput()
	    sk.shutdownOutput() ;
	    
public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务器已经开启,等待连接.....");
        Socket sk = serverSocket.accept();
        InputStream in = sk.getInputStream();
        //包装通道中的输入流
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        BufferedWriter writer = new BufferedWriter(new FileWriter("aaa.txt"));
        String line = null;
        while ((line = reader.readLine()) != null) {
           /* if ("over".equals(line)) {
                break;
            }*/
            // System.out.println(line);
            writer.write(line);
            writer.newLine();
            writer.flush();
        }
        System.out.println("服务端下来了");
        //服务端,给客户端一个反馈,告诉客户端你上传成功了
        OutputStream outputStream = sk.getOutputStream();
        outputStream.write("上传成功!".getBytes());

        writer.close();
        serverSocket.close();
    }
}

网络编程(多线程改进上传文本文件)(理解)

A:案例演示 :	多客户端上传文件,多线程改进
public class TCPClient {
    public static void main(String[] args) throws IOException {
        //客户端读取文本文件服务器控制台输出
        Socket socket = new Socket("192.168.15.100", 9999);

        OutputStream out = socket.getOutputStream();
        //包装通道中的流
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
        BufferedReader reader = new BufferedReader(new FileReader("MyTest.txt"));
        String line = null;
        while ((line = reader.readLine()) != null) {
            writer.write(line);
            writer.newLine();
            writer.flush();
        }
        //下来了,给服务端,手写一个标记,告诉服务端,文件数据传完了
     /*   writer.write("over");
        writer.newLine();
        writer.flush();*/
        /*我们手写一个标记,当然可以,但是要确保,你这个标记,在你上传的文件中不要出现*/
        //另外一个解决方案,你的意思就是想要告诉服务端,我这边传完了,不要让服务端等待了
      /*  void shutdownInput ()
        此套接字的输入流置于“流的末尾”。
        void shutdownOutput ()
        禁用此套接字的输出流。*/
        socket.shutdownOutput();

        //客户端 读取服务端的反馈
        InputStream inputStream = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        String s = new String(bytes, 0, len);
        System.out.println(s);
        reader.close();
        socket.close();
    }
}


public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("9999服务器已经开启等待连接...");
        //循环侦听客户端的连接
        int i = 1;
        while (true) {
            Socket sk = serverSocket.accept();
            System.out.println((i++) + "个客户端连接上来了");
            //为每个连接上来的客户端sk,单独开启线程去操作
            new UpLoadThread(sk).start();
        }
    }
}


public class UpLoadThread extends Thread {
    private Socket sk;

    public UpLoadThread(Socket sk) {
        this.sk = sk;
    }

    @Override
    public void run() {
        try {
            InputStream in = sk.getInputStream();
            //包装通道中的输入流
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            //为了防止覆盖,文件名随机取
            BufferedWriter writer = new BufferedWriter(new FileWriter(System.currentTimeMillis() + "aaa.txt"));
            String line = null;
            while ((line = reader.readLine()) != null) {
                writer.write(line);
                writer.newLine();
                writer.flush();
            }
            System.out.println("服务端下来了");
            //服务端,给客户端一个反馈,告诉客户端你上传成功了
            OutputStream outputStream = sk.getOutputStream();
            outputStream.write("上传成功!".getBytes());
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

DOS 命令意义
net view获取局域网中的所有主机名
ipconfig -all获取本地IP,主机名,MAC地址
arp -a获取本局域网中的所有IP地址和物理地址
ping -a x.x.x.x获取x.x.x.x的主机名
nbtstat -a 主机名获取MAC地址

https://blog.csdn.net/havedream_one/article/details/47071393 参考这篇文档可以提取局域网中其他主机的IP地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值