Java基础(32)计算机网络、网络编程概述、UDP编程、TCP编程

1. 计算机网络

1. 计算机网络

	是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,
	在网络操作系统,网络管理软件及网络通信协议的管理和协调下,
	实现资源共享和信息传递的计算机系统。

2. 网络编程

	就是用来实现网络互连的不同计算机上运行的程序之间可以进行数据的交换

3. 计算机网络模型

  • OSI(Open System Interconnection开放系统互连):七层参考模型
  • TCP/IP四层参考模型
  • OSI七层参考模型与TCP/IP四层参考模型图示

在这里插入图片描述

4. 网络的七层模型概述

	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之类的(可以把它理解成我们在电脑屏幕上可以看到的东西.就是终端应用)。

5. IP地址
(1)IP地址的概述:所谓IP地址就是给每个连接在Internet上的主机分配的一个32bit地址
(2)IP地址的组成:IP地址 = 网络地址+主机地址

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

(3)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

(4)特殊地址

  • 120.0.0.1:本地回环
  • xxx.xxx.xxx.255:广播地址

6. 端口号
(1)物理端口:网卡口
(2)逻辑端口:通常指的端口号就是逻辑端口

  • 每个网络程序都有一个逻辑端口,用于识别进程的逻辑地址,不同进程的标识
  • 有效端口:0 ~ 65535(两个字节),其中0 ~ 1023系统使用或保留端口

7. 传输协议
(1)UDP:发短信

	将数据源和目的封装成数据包中,不需要建立连接;
	每个数据报的大小在限制在64k;
	因无连接,是不可靠协议;
	不需要建立连接,速度快

(2)TCP:打电话,视频聊天

	建立连接,形成传输数据的通道;
	在连接中进行大数据量传输;
	需要连接所以是可靠协议;
	必须建立连接,效率会稍低

2. 网络编程概述

1. 网络编程的三要素
(1)IP地址:InetAddress:网络中设备的标识,不易记忆,可用主机名
(2)端口号:用于标识进程的逻辑地址、不同进程的标识
(3)传输协议:TCP、UDP

2. InetAddress类
(1)InetAddress类的概述:为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress 供我们使用。此类表示互联网协议 (IP) 地址
(2)InetAddress常见功能

	public static InetAddress getByName(String host):在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组
	public String getHostAddress():返回 IP 地址字符串(以文本表现形式)
	public String getHostName():获取此 IP 地址的主机名
public class TestDemo01 {
    public static void main(String[] args) throws Exception {
        //public static InetAddress getByName(String host):在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组
        InetAddress inetAddress = InetAddress.getByName("WZR");

        //public String getHostAddress():返回 IP 地址字符串(以文本表现形式)
        String ip = inetAddress.getHostAddress();
        System.out.println(ip);    //192.168.1.103

        //public String getHostName():获取此 IP 地址的主机名
        String hostName = inetAddress.getHostName();
        System.out.println(hostName);     //WZR


        System.out.println("===========================================");

        //通过主机名也可以获取到InetAddress对象
        InetAddress inetAddress2 = InetAddress.getByName("192.168.1.103");

        String ip2 = inetAddress2.getHostAddress();
        System.out.println(ip2);

        String hostName2 = inetAddress2.getHostName();
        System.out.println(hostName2);

    }
}

3. Socket通信原理
(1)Socket套接字概述:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字
(2)Socket = IP + 端口号
(3)Socket原理机制:

		通信的两端都有Socket
		网络通信其实就是Socket间的通信
		数据在两个Socket间通过IO传输

3. UDP编程

1. UDP协议的Socket套接字:DatagramSocket:此类表示用来发送和接收数据报包的套接字(UDP协议中客户端和服务端发送和接收数据时都使用一个类DatagramSocket)

2. UDP通信的原理
在这里插入图片描述

3. 最原始使用UDP协议发送数据的代码示例

public class UDPClient {
    public static void main(String[] args) throws Exception {
        //1.创建UDP的Socket的客户端
        DatagramSocket ds = new DatagramSocket();

        //2.封装数据包
        /**
         * DatagramPacket类表示数据报包
         *         DatagramPacket( byte[] buf, int length, InetAddress address,int port)
         *         构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
         *         数据报包里面封装:你要发送的数据,数据的长度,对方的IP,对方的端口
         */
        byte[] bytes = "你好UDP".getBytes();
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.1.103"), 8888);

        //3.发送数据包
        ds.send(dp);

        //4.释放资源
        ds.close();

    }
}

===============================================================================================

public class UDPServer {
    public static void main(String[] args) throws Exception{
        //1.创建UDP的Socket的服务端
        //DatagramSocket(int port):创建数据报套接字并将其绑定到本地主机上的指定端口
        DatagramSocket ds = new DatagramSocket(8888);

        //2.封装数据报包
        //DatagramPacket( byte[] buf, int length):构造 DatagramPacket,用来接收长度为 length 的数据包
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);


        /**
         * 等待接收数据,是一个阻塞方法:receive()
         *        从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。
         *        数据报包也包含发送方的 IP 地址和发送方机器上的端口号。
         *        此方法在接收到数据报前一直阻塞
         */
        //3.接收数据
        System.out.println("服务器已开启,等待接受数据");
        ds.receive(dp);   //接收发送的数据,他需要一个空的数据报包,用来装发过来的数据

        //从数据报包中取出数据
        byte[] data = dp.getData();
        //获取从数据包中接受出来的数据的实际长度
        int length = dp.getLength();
        //从数据报包中获取发送者的IP
        String ip = dp.getAddress().getHostAddress();

        //把字节数组恢复成字符串
        String s = new String(data, 0, length);

        System.out.println("ip地址为:" + ip + "给你发送了消息:" + s);

    }
}

===============================================================================================
	运行结果:
		UDPClient:无
		UDPServer:
			服务器已开启,等待接受数据
			ip地址为:192.168.1.103给你发送了消息:你好UDP
	

4. 客户端键盘录入,不断地给服务端发送消息的代码示例

//客户端键盘录入,不断地给服务端发送消息
public class UDPClient {
    public static void main(String[] args) throws Exception{
        DatagramSocket ds = new DatagramSocket();

        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("请输入要发送的数据");

            String s = sc.nextLine();
            byte[] bytes = s.getBytes();

            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.1.103"), 6666);
            ds.send(dp);

            //定义一个结束标记
            if ("886".equals(s)){
                break;
            }
        }

        ds.close();
    }
}

===============================================================================================

public class UDPServer {
    public static void main(String[] args) throws Exception {
        DatagramSocket ds = new DatagramSocket(6666);

        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        System.out.println("服务器已开启,等待接受数据");

        while (true) {
            ds.receive(dp);
            byte[] data = dp.getData();
            int length = dp.getLength();
            String ip = dp.getAddress().getHostAddress();
            int port = dp.getPort();

            String s = new String(data, 0, length);

            System.out.println("IP为:" + ip + ",端口号为:" + port + ",给你发来消息为:" + s);

            if ("886".equals(s)) {
                break;
            }
        }

        ds.close();
    }
}

===============================================================================================

	运行结果:
		UDPClient:
			请输入要发送的数据
			hfaknl
			请输入要发送的数据
			uyubz
			请输入要发送的数据
			2132
			请输入要发送的数据
			vhkxhi
			请输入要发送的数据
			886
		UDPServer:
			服务器已开启,等待接受数据
			IP为:192.168.1.103,端口号为:59296,给你发来消息为:hfaknl
			IP为:192.168.1.103,端口号为:59296,给你发来消息为:uyubz
			IP为:192.168.1.103,端口号为:59296,给你发来消息为:2132
			IP为:192.168.1.103,端口号为:59296,给你发来消息为:vhkxhi
			IP为:192.168.1.103,端口号为:59296,给你发来消息为:886

4. 使用多线程来进行数据发送的代码示例

(1)使用多线程来进行数据发送的原理
在这里插入图片描述
(2)代码实现

public class Boy {
    public static void main(String[] args) throws Exception {
        //开启子线程,用来接收Girl发来的消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    DatagramSocket ds = new DatagramSocket(9999);

                    byte[] bytes = new byte[1024];
                    DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

                    System.out.println("Boy服务器已开启,等待接受数据");

                    while (true){
                            ds.receive(dp);

                            byte[] data = dp.getData();
                            int length = dp.getLength();
                            String ip = dp.getAddress().getHostAddress();
                            int port = dp.getPort();
                            String s = new String(data, 0, length);

                            System.out.println("IP为:" + ip + ",端口号为:" + port + ",Girl给你发来消息为:" + s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //主线程,用来给Girl发消息
        sendMsg();
    }

    private static void sendMsg() throws Exception{
        DatagramSocket ds = new DatagramSocket();
        Scanner sc = new Scanner(System.in);

        while (true){
            System.out.println("请输入你要发送给Girl的消息");
            String s = sc.nextLine();
            byte[] bytes = s.getBytes();

            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("WZR"), 8888);
            ds.send(dp);

            if ("886".equals(s)){
                break;
            }
        }
    }
}

===============================================================================================

public class Girl {
    public static void main(String[] args) throws Exception {
        //开启子线程,用来接收Boy发来的消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    DatagramSocket ds = new DatagramSocket(8888);

                    byte[] bytes = new byte[1024];
                    DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

                    System.out.println("Girl服务器已开启,等待接受数据");

                    while (true){
                        ds.receive(dp);

                        byte[] data = dp.getData();
                        int length = dp.getLength();
                        String ip = dp.getAddress().getHostAddress();
                        int port = dp.getPort();
                        String s = new String(data, 0, length);

                        System.out.println("IP为:" + ip + ",端口号为:" + port + ",Boy给你发来消息为:" + s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //主线程,用来给Boy发消息
        sendMsg();
    }

    private static void sendMsg() throws Exception{
        DatagramSocket ds = new DatagramSocket();
        Scanner sc = new Scanner(System.in);

        while (true){
            System.out.println("请输入你要发送给Boy的消息");
            String s = sc.nextLine();
            byte[] bytes = s.getBytes();

            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("WZR"), 9999);
            ds.send(dp);

            if ("886".equals(s)){
                break;
            }
        }
    }
}

===============================================================================================

运行结果:
		Boy:
			Boy服务器已开启,等待接受数据
			请输入你要发送给Girl的消息
			在吗妹妹
			请输入你要发送给Girl的消息
			IP为:192.168.1.103,端口号为:49287,Girl给你发来消息为:在的哥哥
			约吗
			请输入你要发送给Girl的消息
			IP为:192.168.1.103,端口号为:49287,Girl给你发来消息为:不约,晚上和男朋友在一起呢
			好的吧
			请输入你要发送给Girl的消息
			IP为:192.168.1.103,端口号为:49287,Girl给你发来消息为:下次约
			886
			IP为:192.168.1.103,端口号为:49287,Girl给你发来消息为:886
		
		Girl:
			Girl服务器已开启,等待接受数据
			请输入你要发送给Boy的消息
			IP为:192.168.1.103,端口号为:49286,Boy给你发来消息为:在吗妹妹
			在的哥哥
			请输入你要发送给Boy的消息
			IP为:192.168.1.103,端口号为:49286,Boy给你发来消息为:约吗
			不约,晚上和男朋友在一起呢
			请输入你要发送给Boy的消息
			IP为:192.168.1.103,端口号为:49286,Boy给你发来消息为:好的吧
			下次约
			请输入你要发送给Boy的消息
			IP为:192.168.1.103,端口号为:49286,Boy给你发来消息为:886
			886

4. TCP编程

1. TCP通信:通信两端需要建立连接,属于可靠协议,传输数据大小无限制。要严格区分客户端与服务端

2. TCP通信的图示
在这里插入图片描述

3. 客户端:Socket

	构造方法:
			public Socket(String host, int port):创建套接字对象并将其连接到指定主机上的指定端口号
	
	成员方法:
			public InputStream getInputStream():返回此套接字的输入流
			public OutputStream getOutputStream() : 返回此套接字的输出流
			public void close() :关闭此套接字
			public void shutdownOutput() : 禁用此套接字的输出流

4. 服务器端:ServerSocket

	构造方法:
			public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指
	定的端口号上,参数port就是端口号
	
	成员方法:
			public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法
	会一直阻塞直到建立连接

5. 最原始使用TCP协议发送数据的代码示例

public class TCPClient {
    public static void main(String[] args) throws Exception {
        //1.创建客户端的Socket,并指定服务端的IP和端口
        Socket socket = new Socket("127.0.0.1", 8888);

        //2.获取通道中的输出流
        OutputStream os = socket.getOutputStream();

        //3.通过输出流来获取数据
        os.write("你好TCP,我来了".getBytes());

        //4.释放资源
        socket.close();
    }
}

===============================================================================================

public class TCPServer {
    public static void main(String[] args) throws Exception {
        //1.创建ServerSocket并绑定到特定端口的服务器套接字,并暴露端口号
        ServerSocket serverSocket = new ServerSocket(8888);

        System.out.println("服务端已开启,等待连接");

        //2.侦听客户端的连接
        //accept() 侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞
        Socket socket = serverSocket.accept();

        //3.获取数据

        //3.1 获取通道中的输入流
        InputStream is = socket.getInputStream();

        //3.2 获取数据
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        String s = new String(bytes, 0, len);

        String ip = socket.getInetAddress().getHostAddress();
        System.out.println("IP为:" + ip + "的客户端给你发来消息:" + s);

        serverSocket.close();
    }
}

===============================================================================================

运行结果:
	客户端:无
	服务器端:
			服务端已开启,等待连接
			IP为:127.0.0.1的客户端给你发来消息:你好TCP,我来了

6. 客户端发送数据,服务器接受数据并给出反馈的代码示例

public class TCPClient {
    public static void main(String[] args) throws Exception{
        Socket socket = new Socket("127.0.0.1", 9999);

        OutputStream os = socket.getOutputStream();
        os.write("你好TCP服务端,我来了".getBytes());

        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        System.out.println(new String(bytes,0,len));

        socket.close();
    }
}

===============================================================================================

public class TCPServer {
    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = new ServerSocket(9999);

        System.out.println("服务器已经开启,等待连接");
        Socket socket = serverSocket.accept();

        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        System.out.println(new String(bytes,0,len));

        OutputStream os = socket.getOutputStream();
        os.write("你好TCP客户端,已经接收到你的消息了".getBytes());

        serverSocket.close();
    }
}

===============================================================================================

运行结果
		客户端:
				你好TCP客户端,已经接收到你的消息了
		服务器端:
				服务器已经开启,等待连接
				你好TCP服务端,我来了

7. 客户端键盘录入服务器控制台输出的代码示例

public class TCPClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 7777);
        Scanner sc = new Scanner(System.in);

        while(true){
            OutputStream os = socket.getOutputStream();
            System.out.println("请输入要说的话");
            String s = sc.nextLine();
            if ("886".equals(s)){
                break;
            }

            os.write(s.getBytes());
            os.write("\r\n".getBytes());
        }

        socket.close();
    }
}

===============================================================================================

public class TCPServer {
    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = new ServerSocket(7777);

        System.out.println("服务器已开启,等待接收");
        Socket socket = serverSocket.accept();

        InputStream is = socket.getInputStream();

        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = is.read(bytes)) != -1){
            System.out.println(new String(bytes,0,len));
        }
    }
}

===============================================================================================

运行结果:
		客户端:
				请输入要说的话
				nihao
				请输入要说的话
				hahaha
				请输入要说的话
				520
				请输入要说的话
				886
		服务器端:
				服务器已开启,等待接收
				nihao
				
				
				hahaha
				
				
				520

8. 客户端键盘录入服务器写到文本文件的代码示例

public class TCPClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 7777);
        Scanner sc = new Scanner(System.in);

        while(true){
            OutputStream os = socket.getOutputStream();
            System.out.println("请输入要说的话");
            String s = sc.nextLine();
            if ("886".equals(s)){
                break;
            }
            os.write(s.getBytes());
        }

        socket.close();
    }
}

===============================================================================================

public class TCPServer {
    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = new ServerSocket(7777);

        System.out.println("服务器已开启,等待接收");
        Socket socket = serverSocket.accept();

        FileOutputStream fos = new FileOutputStream("msg.txt");

        InputStream is = socket.getInputStream();

        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = is.read(bytes)) != -1){
            fos.write(bytes,0,len);
            fos.write("\r\n".getBytes());
        }

        fos.close();
    }
}

===============================================================================================

运行结果:
	msg.txt
			nihao
			zai?
			haha

9. 客户端读取文本文件,服务器控制台输出的代码示例

public class TCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 7777);
        FileInputStream fis = new FileInputStream("msg.txt");

        OutputStream os = socket.getOutputStream();

        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fis.read(bytes)) != -1){
            os.write(bytes,0,len);
        }

        System.out.println("读取并发送完毕...");
        socket.close();
        fis.close();
    }
}

===============================================================================================

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(7777);

        System.out.println("服务端已经开启,等待连接。。。。。");
        Socket socket = serverSocket.accept();

        InputStream is = socket.getInputStream();

        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = is.read(bytes)) != -1){
            System.out.println(new String(bytes,0,len));
        }
    }
}

===============================================================================================

运行结果:
		客户端:
				读取并发送完毕...
		服务器端:
				服务端已经开启,等待连接。。。。。
				nihao
				zai?
				hahaha

10. TCP协议上传文本文件的代码示例
(1)需求:TCP协议上传文本文件(客户端读取文本文件发送数据到服务器端,服务器端读取数据存储到文本文件中)
(2)代码示例

public class TCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 9797);

        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();

        BufferedReader br = new BufferedReader(new FileReader("msg.txt"));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));

        String line = null;
        while ((line = br.readLine()) != null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        System.out.println("读取并写入完成...");

        socket.close();
        bw.close();

    }
}

===============================================================================================

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9797);
        System.out.println("服务器已开启,等待连接...");

        Socket socket = serverSocket.accept();

        OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();

        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        BufferedWriter bw = new BufferedWriter(new FileWriter("new_msg.txt"));
        String line = null;

        while ((line = br.readLine()) != null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        System.out.println("读取并写入完成...");
        serverSocket.close();
        bw.close();
    }
}

===============================================================================================

运行结果:
		客户端:
				读取并写入完成...
		服务器端:
				服务器已开启,等待连接...
				读取并写入完成...

		new_msg.txt:
				nihao
				zai?
				hahaha

11. TCP上传文本文件并给出反馈的代码示例

public class Client {
    public static void main(String[] args) throws Exception {
        FileInputStream fis = new FileInputStream("timg.jpg");

        Socket socket = new Socket("127.0.0.1", 8888);
        OutputStream os = socket.getOutputStream();

        int len = 0;
        byte[] bytes = new byte[1024 * 8];
        while ((len = fis.read(bytes)) != -1){
            os.write(bytes,0,len);
        }

        //上传完文件写一个结束标记
        socket.shutdownOutput();

        InputStream is = socket.getInputStream();
        while ((len = is.read(bytes)) != -1){
            System.out.println(new String(bytes,0,len));
        }

        fis.close();
        socket.close();
    }
}

===============================================================================================

public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8888);

        Socket socket = serverSocket.accept();
        InputStream is = socket.getInputStream();

        FileOutputStream fos = new FileOutputStream("newtimg.jpg");

        int len = 0;
        byte[] bytes = new byte[1024 * 8];
        while ((len = is.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }


        socket.getOutputStream().write("上传成功".getBytes());

        fos.close();
        socket.close();
        serverSocket.close();
    }
}

12. 使用多线程来进行TCP上传文本文件并给出反馈的代码示例

public class TCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 9999);

        OutputStream os = socket.getOutputStream();

        FileInputStream fis = new FileInputStream("msg.txt");
        int len = 0;
        byte[] bytes = new byte[1024];
        while((len = fis.read(bytes)) != -1){
            os.write(bytes,0,len);
            os.flush();
        }

        socket.shutdownOutput();

        //读取服务器反馈
        byte[] bytes2 = new byte[1024];
        int len2 = 0;
        System.out.println(new String(bytes2,0,len2));

        socket.close();
        fis.close();
    }
}

===============================================================================================

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务器已开启,等待连接...");

        int i = 1;
        while (true) {
            Socket socket = serverSocket.accept();
            System.out.println("第" + (i++) + "个客户端已连接");
            //为每一个连接上来的客户端,单独开启一个线程
            //把每个客户端的socket传入线程中
            new UpLoadThread(socket).start();
        }
    }
}

===============================================================================================

public class UpLoadThread extends Thread{
    private Socket socket;

    public UpLoadThread(Socket socket){

        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();

            FileOutputStream fos = new FileOutputStream(System.currentTimeMillis() + "msg.txt");

            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = is.read(bytes)) != -1){
                fos.write(bytes,0,len);
                fos.flush();
            }

            fos.write("客户端你好,上传的文件已经收到了".getBytes());
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

===============================================================================================

运行结果:
		客户端:
				客户端你好,上传的文件已经收到了
		服务器:
				服务器已开启,等待连接...1个客户端已连接
				第2个客户端已连接
				第3个客户端已连接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值