Java网络编程入门


1、网络编程入门

1.1、网络编程概述

1.2、网络编程三要素

IP地址

  • 要想让网络中的计算机互相通信,必须为每台计算计指定一个标识号,即IP。

端口

  • 网络的通信,本质上是两个应用程序之间的通信。端口号可以唯一标识设备中的应用程序。
  • 设备上应用程序的唯一标识。
  • 用两个字节表示,取值范围是0~65535。其中0-1023之间的端口号用于一些知名网络服务和应用。
  • 普通的应用程序需使用1024以上的端口号。
  • 如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

协议

  • 计算机网络中,连接和通信的规则被称为网络通信协议。
  • 通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时要遵守一定的规则。在计算机网络中,这些连接和通信的规则被称为网络通信协议。
  • 网络通信协议对数据的格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。
  • 常见的有UDP协议和TCP协议。

1.3、UDP和TCP

UDP协议:

  • 用户数据报协议(User Datagram Protocol)
  • UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不退立逻辑连接。简单来说,当一台计算机向另一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
  • 由于UDP协议消耗资源小,通信效率高,所以通常用于音频、视频和普通数据的传输。
  • 例如视频会议通常采用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。

TCP协议:

  • 传输控制协议(Transmission Control Protocol)
  • TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。

三次握手:

  • TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
  • 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
  • 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
  • 第三次握手,客户端再次向服务器端发送确认信息,确认连接。
  • 完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。例如上传文件、下载文件、浏览网页等。

1.4、InetAddress的使用

用途:

  • 对IP地址的获取和操作
  • InetAddress:此类表示Internet协议(IP)地址。
方法名用途
static InetAddress getByName(String host)确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName()获取此IP地址的主机名
String getHostAddress()返回文本显示的IP地址字符串
package com.test;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
//        InetAddress address= InetAddress.getByName("chuhe");
        InetAddress address=InetAddress.getByName("192.168.0.1");

        String name=address.getHostName();
        String ip=address.getHostAddress();

        System.out.println("主机名:"+name);
        System.out.println("IP地址:"+ip);
    }
}

2、UDP通信程序

2.1、UDP通信原理

-. UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象。因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念。

  • Java提供了DatagramSocket类作为基于UDP协议的Socket。

2.2、UDP发送数据

UDP发送数据的步骤:

  1. 创建发送端的Socket对象(DatagramSocket)。
  2. 创建数据,并把数据打包。
  3. 调用DatagramSocket对象的方法发送数据。
  4. 关闭发送端。
package com.test1;

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;

public class SendDemo {
    public static void main(String[] args) throws IOException {
        //1. 创建发送端的Socket对象(DatagramSocket)
        DatagramSocket ds=new DatagramSocket();
        //2. 创建数据,并把数据打包。
        byte[] bys="Hello UDP".getBytes();
        int length=bys.length;
        InetAddress address= InetAddress.getByName("192.168.0.102");
        int port=31400;
        DatagramPacket dp=new DatagramPacket(bys,length,address,port);
        //3.调用DatagramSocket对象的方法发送数据。
        ds.send(dp);
       //4. 关闭发送端。
        ds.close();

    }
}

2.3、UDP接收数据

UDP接收数据的步骤:

  1. 创建接收端的Socket对象(DatagramSocket)
  2. 创建一个数据包,用于接收数据
  3. 调用DatagramSocket对象的方法接收数据
  4. 解析数据包,并把数据在控制台显示
  5. 关闭接收端
package com.test1;

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

public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds=new DatagramSocket(31400);

        byte[] bys=new byte[1024];
        DatagramPacket dp=new DatagramPacket(bys,bys.length);
        //接收数据
        ds.receive(dp);
        //解析数据包
        byte[] data = dp.getData();
        int length=dp.getLength();//返回发送或接收数据的实际长度,这里为接收
        String dataString=new String(data,0,length,"UTF-8");
        System.out.println(dataString);
        //关闭接收数据
        ds.close();
    }
}

2.4、UDP通信案例

发送端:

package com.test2;

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


public class SendDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds=new DatagramSocket();
        //自己封装键盘录入数据
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String line;

        while((line=br.readLine())!=null){
            if(line.equals("886")){
                break;
            }
            byte[] bys=line.getBytes("UTF-8");
            int length=bys.length;
            int port=31400;

            InetAddress address=InetAddress.getByName("127.0.0.1");
            DatagramPacket dp=new DatagramPacket(bys,length,address,port);
            ds.send(dp);
        }
        ds.close();

    }
}


接收端:

package com.test2;

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


public class ReciveDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds=new DatagramSocket(31400);
        while(true){
            byte[] bys=new byte[1024];
            DatagramPacket dp=new DatagramPacket(bys,bys.length);

            ds.receive(dp);
            byte[] data = dp.getData();
            String str=new String(data,0,dp.getLength(),"UTF-8");
            System.out.println(str);

        }
        //关闭接收端
        //ds.close();

    }
}

3、TCP通信程序

3.1、TCP通信原理

  • TCP通信协议是一种可靠的网络协议,它在通信的两端各建立 一个Socker对-象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟网络链路,两端的程序可以通过虚拟链路进行通信。
  • Java使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
  • Java为客户端提供了Socket类,为服务端提供了ServerSocket类。

3.2、TCP发送数据

发送数据的步骤:

  1. 创建客户端的Socket对象(Socket)
  2. 获取输出流,写数据
  3. 释放资源
package com.test3;

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


public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket
       // Socket s=new Socket(InetAddress.getByName("192.168.0.2"),31400);
        Socket s=new Socket("192.168.0.2",31400);

        //获取输出流,写数据
        OutputStream os = s.getOutputStream();
        os.write("Hello tcp".getBytes("UTF-8"));

        //释放资源
        s.close();


    }
}

3.3、TCP接收数据

接收数据的步骤:

  1. 创建服务器端的Socket对象(ServerSocket)
  2. 监听客户端连接,返回一个Socket对象
  3. 获取输入流,读数据,并把数据显示在控制台
  4. 释放资源
package com.test3;

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

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket ss=new ServerSocket(31400);

        //侦听要连接到此套接字并接受
        Socket socket = ss.accept();
        //输取输入流
        InputStream is = socket.getInputStream();
        byte[] bys=new byte[1024];
        int len=is.read(bys);
        String data=new String(bys,0,len,"UTF-8");
        System.out.println(data);

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

3.4、服务端给出反馈

服务端:

package com.test4;

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

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(31400);

        Socket socket=ss.accept();

        //获取输入流,读数据
        InputStream is=socket.getInputStream();
        byte[] bys=new byte[1024];
        int len=is.read(bys);
        String str=new String(bys,0,len,"UTF-8");
        System.out.println(str);

        //反馈数据
        OutputStream os=socket.getOutputStream();
        os.write("数据已收到".getBytes("UTF-8"));

        //释放资源
        //socket.close();//ss释放socket对象也会自动释放
        ss.close();


    }
}

客户端:

package com.test4;

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


public class ClientDemo {
    public static void main(String[] args) throws IOException {
        //创建客户端Socket
        Socket s=new Socket("192.168.0.102",31400);

        //获取输出字节流,写数据
        OutputStream os=s.getOutputStream();
        os.write("Hello tcp".getBytes("UTF-8"));

        //接收服务器反馈
        InputStream is=s.getInputStream();
        byte[] bys=new byte[1024];
        int len=is.read(bys);
        String str=new String(bys,0,len,"UTF-8");
        System.out.println(str);

        //释放资源
        s.close();
    }
}

3.5、客户端数据来自于键盘输入

服务端:

package com.test5;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(31400);

        //监听客户端的连接
        Socket s=ss.accept();

        //获取输入流
        InputStream is=s.getInputStream();
        InputStreamReader isr=new InputStreamReader(is,"UTF-8");
        BufferedReader br=new BufferedReader(isr);

        String line;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }

        //释放资源
        ss.close();

    }
}


客户端

package com.test5;

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

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Socket s=new Socket("192.168.0.102",31400);
        //数据来自于键盘录入
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        //封装输出流对象(这里封装的是字符流,如果传图片需要封装字节流)
        OutputStream os=s.getOutputStream();
        OutputStreamWriter osw=new OutputStreamWriter(os,"UTF-8");
        BufferedWriter bw=new BufferedWriter(osw);

        String line;
        while((line=br.readLine())!=null){
            if("886".equals(line)){
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //释放资源
        s.close();
    }
}

3.6、服务端写入文件

服务端

package com.test6;

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

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket ss=new ServerSocket(31400);

        //监听客客户端连接,返回一个Socket对象
        Socket s=ss.accept();

        //获取输入流,读数据,即接收数据
        InputStream is=s.getInputStream();
        InputStreamReader isr=new InputStreamReader(is,"UTF-8");
        BufferedReader br=new BufferedReader(isr);

        //把数据写入文本文件
        /*
        //不能控制编码
        FileWriter fw=new FileWriter("D:\\test\\a.txt");
        BufferedWriter bw=new BufferedWriter(fw);
        */
        //可以控制编码
        FileOutputStream fos=new FileOutputStream("D:\\test\\a.txt",true);
        OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8");
        BufferedWriter bw=new BufferedWriter(osw);


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

        }

        //释放资源
        fos.close();
        ss.close();

    }
}

客户端

package com.test6;

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

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Socket s=new Socket("192.168.0.102",31400);

        //输入字符流,输入来自键盘录入
        InputStream is=System.in;
        InputStreamReader isr=new InputStreamReader(is,"UTF-8");
        BufferedReader br=new BufferedReader(isr);

        //输出字符流
        OutputStream os=s.getOutputStream();
        OutputStreamWriter osw=new OutputStreamWriter(os,"UTF-8");
        BufferedWriter bw=new BufferedWriter(osw);

        String line;
        while((line=br.readLine())!=null){
            if("886".equals(line)){
                break;
            }

            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        s.close();

    }
}

3.7、客户端数据来自于文本

服务端

package com.test7;

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

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

        ServerSocket ss=new ServerSocket(31400);
        //监听端口,获取Socket对象
        Socket s=ss.accept();
        //输入流,读数据
        BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
        //输出流,写数据
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\test\\.b.txt"),"UTF-8"));

        String line;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //释放资源
        s.close();
        bw.close();
    }
}

客户端

package com.test7;

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

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        String ip="192.168.0.102";
        int port=31400;
        Socket s=new Socket(ip,port);

        //输入流,读数据
        BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\test\\a.txt"),"UTF-8"));
        //输出流,写数据
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));

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

        //释放资源
        br.close();
        s.close();
    }
}

3.8、上传服务端给出反馈

服务端

package com.test7;

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

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

        ServerSocket ss=new ServerSocket(31400);
        //监听端口,获取Socket对象
        Socket s=ss.accept();
        //输入流,读数据
        BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
        //输出流,写数据
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\test\\.b.txt"),"UTF-8"));

        String line;
        while((line=br.readLine())!=null){//等待读取数据
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        //给出反馈
        BufferedWriter bwServer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
        bwServer.write("文件上传成功");
        bwServer.newLine();
        bwServer.flush();

        //释放资源
        s.close();
        bw.close();
    }
}

客户端

package com.test7;

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

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

        Socket s=new Socket("192.168.0.102",31400);

        //输入流,读数据
        BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\test\\a.txt"),"UTF-8"));
        //输出流,写数据
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));

        String line;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //输出结束,只有终止了输出,服务端才能结束读取Socket
        s.shutdownOutput();

        //接收反馈,读Socket
        BufferedReader brClient=new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
        String data=brClient.readLine();
        System.out.println("服务器的反馈:"+data);


        //释放资源
        br.close();
        s.close();
    }
}

3.9、多现程实现文件上传

服务端

package com.test8;

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

public class ServerDemo {
    public static void main(String[] args) throws IOException {
        //创建服务器Socket对象
        ServerSocket ss=new ServerSocket(31400);

        while(true){
            //监听客户端连接,返回一个Socket对象
            Socket s=ss.accept();
            //为每一个客户端开启一个线程
//        ServerThread st=new ServerThread(s);
//        Thread th=new Thread(st);
//        th.start();
            new Thread(new ServerThread(s)).start();
        }

        //ss.close();//不需要释放资源
    }
}

多线程

package com.test8;

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

public class ServerThread implements Runnable {
    private Socket s;
    public ServerThread(Socket s) {
        this.s=s;
    }

    @Override
    public void run() {
        try{
            //接收数据写入文本文件
            BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
            //BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\test\\b.txt"),"UTF-8"));
            //解决重名
            int count=0;
            File file=new File("D:\\test\\b"+count+".txt");
            while(file.exists()){
                count++;
                file=new File("D:\\test\\b"+count+".txt");
            }
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8"));

            String line;
            while((line=br.readLine())!=null){
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            //给出反馈
            BufferedWriter bwServer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
            bwServer.write("文件上传成功");
            bwServer.newLine();
            bwServer.flush();

            bwServer.write("下次再来");
            bwServer.newLine();
            bwServer.flush();

            //释放资源
            bw.close();
            s.close();

        }catch(IOException e){
            e.printStackTrace();
        }

    }
}

客户端

package com.test8;

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

public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Socket s=new Socket("192.168.0.102",31400);
        //输入流,读文件
        BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\test\\a.txt"),"UTF-8"));
        //输出流,写入到Socket
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));

        String line;
        while((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //终止写入Socket
        s.shutdownOutput();

        //接收反馈
        BufferedReader brClient=new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
        String data;
        while((data=brClient.readLine())!=null){
            System.out.println("服务器反馈:"+data);
        }


        //释放资源
        br.close();
        s.close();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值