JAVA#(四)网络编程基础

本文介绍了Java网络编程基础知识,包括Socket、HTTP协议的代码实现,UDP协议示例,通过URL下载数据的方法,以及即时传输(创建对话)的实现。详细讲解了TCP/IP模型和相关协议,并提供了实用的编程实例。
摘要由CSDN通过智能技术生成

网络编程基础

参考文章:https://www.cnblogs.com/swordfall/p/10781281.html
整理总结:
IOS模型
TCP/IP模型
模型及其对应层次的协议即作用
IP协议
TCP协议
UDP协议
HTTP协议
HTTPS协议

Socket

Socket,实际上是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
Socket的出现,只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口,比如create、listen、accept、send、read和write等等。

解决问题:主要解决如何包装数据
socket的全部流程

HTTP协议实现代码实例

普通流传输
Client:

  • 构建TCP协议实现类对象socket,方便按照TCP协议建立连接
  • 实现socket,让socket有实际意义,只需要将IP和端口就能确定本线程的目标
  • 从socket那里构建一个输出流,方便数据写入输出流
  • 将数据写入输出流后,关闭输出流,再关闭socket
    Server:
  • 通过给ServerSocket对象赋值,开启端口,以便接收数据
  • ServerSocket对象可以接收从端口得到传来的Socket对象A
  • 然后可以从A中获得到输入流,再从输入流中获取数据(定义输出流来输出输入流中的数据)
  • 关闭输出流,再关闭输入流,最后关闭socket和serverSocket
public class Client {
    public static void main(String[] args) {
        client();
    }
    public static void client(){
        OutputStream output = null;
        Socket socket = null;
        try {
            InetAddress localHost = InetAddress.getByName("127.0.0.1");
            socket = new Socket(localHost,8848);
            output = socket.getOutputStream();
            output.write("hello I'm the client".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(output != null){
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

public class Server {
    public static void main(String[] args) {
        server();
    }
    public static void server() {
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream input = null;
        ByteArrayOutputStream out = null;
        try {
            serverSocket = new ServerSocket(8848);
            socket = serverSocket.accept();
            System.out.println("client IP: " + socket.getInetAddress());
            input = socket.getInputStream();
            /*
            一般不建议这样书写,数据传输时可能会出现乱码!!
            byte[] buffer = new byte[1024];
            int len;
            while((len = input.read(buffer)) != -1){
                String data = new String(buffer,0,len);
                System.out.println(data);
            }*/

            out = new ByteArrayOutputStream();
            byte[] buffer = new byte[10];
            int len;
            while((len = input.read(buffer)) != -1){
                out.write(buffer,0,len);
            }
            System.out.println(out.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(input != null){
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

文件流传输
Client:将文件传递给服务器

  • 创建文件,得到文件用来创建文件流
  • 定义socket,设定socket的ip,port,输出流
  • 通过输入流将文件流放入socket的输出流中
  • 传递完毕后,关闭输入流,在关闭输出流,最后关闭socket
    Server:收到文件将其保存在本地文件中
  • 创建ServerSocket,指定端口后可以通过SereverSocket获得这个端口传来的Socket
  • 获得到Socket后,去得到里面的输入流
  • 建立文件输出流来获得Socket的输入流
  • 关闭文件输出流,再关闭socket中的输入流,然后关闭socket对象,最后关闭serverScoket
public class TcpClientDemo02 {
	public static void main(String[] args) throws Exception {
		
			Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
			OutputStream os = socket.getOutputStream();
			File file = new File("src/web_study_lession2/asd.jpg");
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
			
			byte[] buffer = new byte[1024];
			int len;
			while((len = bis.read(buffer))!= -1) {
				os.write(buffer,0,len);
			}
			
			bis.close();
			os.close();
			socket.close();
	}
}
public class TcpSeverDemo02 {
	public static void main(String[] args) throws Exception {
		ServerSocket serverSocket = new ServerSocket(9000);
		System.out.println("已经打开端口9000,等待客服端连接");
		Socket accept = serverSocket.accept();//阻塞式监听,会一直监听,直到监听到
		System.out.println("连接客服端的IP:"+accept.getInetAddress());

		InputStream is = accept.getInputStream();
		File receive = new File("receive.txt");
		if(!receive.exists()){
			receive.createNewFile();
		}
		FileOutputStream fos = new FileOutputStream(receive);
		
		byte[] buffer = new byte[1024];
		int len;
		while((len = is.read(buffer))!= -1) {
			fos.write(buffer, 0, len);
		}
		fos.close();
		is.close();
		accept.close();
		serverSocket.close();
	}
}

UDP协议实现代码实例

客服端将数据报发送到服务端
服务端:
1.打开端口
2.接收数据包
3.处理数据包
4.关闭连接

public class UdpServerDemo {
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket socket = new DatagramSocket(9090);
        // 接收数据
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
        socket.receive(packet);
        //关闭连接
        socket.close();

        //输出包中内容
        System.out.println(packet.getAddress().getHostAddress());
        System.out.println(new String(packet.getData(),0, packet.getLength()));
    }
}

服务端:
1.确定目标(ip和端口)
2.建立包
3.发送包

public class UdpClientDemo {
    public static void main(String[] args) throws Exception {
        //建立socket通信
        DatagramSocket socket = new DatagramSocket();
        //建立包
        String msg = "nihao";
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9090;
        DatagramPacket packet = new DatagramPacket(msg.getBytes(),0, msg.getBytes().length, localhost, port);
        //发送包
        socket.send(packet);
    }
}

通过url下载数据

1.创建url
2.通过url获得连接
3.在连接上获得输入流
4.创建自己的输出流用来输出文件
5.将输入流转化为输出流
6.关闭输出流,输入流,连接

public class UrlDown {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://m801.music.126.net/20210503215010/1395364ef0339e371ea7b50e104ba131/jdyyaac/025e/540b/5408/54ea83527dca9d54d4cbcbdbb445a2d5.m4a");

        URLConnection urlConnection = (HttpURLConnection)url.openConnection();

        InputStream inputStream = urlConnection.getInputStream();

        FileOutputStream fos = new FileOutputStream("a.m4a");
        byte[] buffer = new byte[1024];
        int len;
        while((len = inputStream.read(buffer))!= -1){
            fos.write(buffer,0, len);
        }
        fos.close();
        inputStream.close();
        ((HttpURLConnection) urlConnection).disconnect();

    }
}

即时传输(创建对话)

一.发送端对应的类
1.创建发送端的socket
2.创建输入流(调用输入),再将其包装成Reader
3.将其线程化(实现Runnable)
4.运行此类时:
将流转换为字符串,再将字符串转化为字节
将字节打包成数据报
通过socket把数据报传出
添加结束判断,如果输入流转化为字符串后有"bye"那么跳出循环(结束线程)

public class TalkSend implements Runnable{
    DatagramSocket socket = null;
    BufferedReader reader= null;

    private int fromPort;
    private String toIP;
    private int toPort;

    public TalkSend(int fromPort,String toIP,int toPort){
        this.fromPort = fromPort;
        this.toIP = toIP;
        this.toPort = toPort;

        try{
            socket = new DatagramSocket(fromPort);
            reader = new BufferedReader(new InputStreamReader(System.in));
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    @Override
    public void run(){
        while(true){
            try{
                String data = reader.readLine();
                byte[] dataBytes = data.getBytes();
                DatagramPacket packet = new DatagramPacket(dataBytes,0,dataBytes.length,
                        new InetSocketAddress(this.toIP,this.toPort));

                socket.send(packet);
                if(data.equals("bye")){
                    break;
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        socket.close();
    }
}

二.接收端对应的类
1.创建接收端的socket
2.将其线程化(实现Runnable)
3.运行此类时:
创建数据报来接收传过来的数据报
将数据报转化为字节数组,再转化为字符串
做结束进程判断(若接收到的字符串有bye,那么结束进程)

public class TalkReceive implements Runnable{

    DatagramSocket socket = null;
    private int port;
    private String msgfrom;
    public TalkReceive(int port,String msgfrom){
        this.port = port;
        this.msgfrom = msgfrom;
        try{
            //DatagramSocket socket = new DatagramSocket(port);
            this.socket = new DatagramSocket(port);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        while(true){
            try {
                byte[] buffer = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
                socket.receive(packet);

                byte[] data = packet.getData();
                String receiveData = new String(data, 0, packet.getLength());
                //注意接收数据包中内容时开始为0,终止用packet.getLength(),不能用data.lenth,否则乱码
                System.out.println(msgfrom+":"+receiveData);
                System.out.println("qwerasd");
                //如果传来的数据是bye则断开接收
                if(receiveData.trim().equals("bye")){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

三.应用接收和发送类实现互交
1.创建两个实现对象类
2.两个都调用接收线程和发送线程

public class TalkTeather {
    public static void main(String[] args) {
        new Thread(new TalkSend(5555,"localhost",8999)).start();
        new Thread(new TalkReceive(9999,"student")).start();
    }
}
public class TalkStudent {
    public static void main(String[] args) {
        new Thread(new TalkSend(7777,"localhost",9999)).start();
        new Thread(new TalkReceive(8999,"teacher")).start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值