网络编程

1.基本原理

网络连接需要两端,客户端和服务器端。

客户端与服务端需要socket连接

客户端服务端端口号要一致

2.客户端

  1. 客户端需要地址,端口号
    InetAddress severIp = InetAddress.getByName("127.0.0.1");
    
  2. 客户端需要主动创建socket\
    socket = new Socket(severIp, port);//服务器使用的端口号
    
  3. 客户端的socket获得一个向外输出的流
    os = socket.getOutputStream();
    os.write("zhaox第一次网络编程".getBytes());
    

3.服务端

  1. 创建一个空Socket
    serverSocket = new ServerSocket(9999);//服务器自己要使用的端口号
    
  2. 等待客户端的socket传过来
    socket = serverSocket.accept();
    
  3. 得到socket的输入流
    is = socket.getInputStream();
    

4.缓冲区

baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
    //read(byte[])方法的返回值为实际读取的字节数
    //read(byte[])方法是一次读取一格byte数组,且满了就覆盖重读
    //read方法返回值为读取字节的ascii码
    baos.write(buffer, 0, len);

    //baos流为什么会出现?
    //因为如果直接读取len会造成汉字割裂,直接读取buffer也会造成最后一个汉字割裂
    //如果将其读取到buffer里,再放到baos里,不会造成割裂,因为是把内容完整的放到了输出管道里
}
System.out.println(baos.toString());

5.文件上传

基本与通信相似

与通信不同的地方

  1. 需要把文件变成文件输入流
  2. 通过输入流给到输出流
  3. 客户端要确定服务端接收完毕,服务端要发送通知给服务端

6.UDP消息发送

1.客户端

  1. 建立一个数据报socket

  2. 确定发送给谁(ip和地址)

  3. 建立包(里面写信息和目标)

  4. 发送

  5. 关闭

    //1. 建立一个socket
    DatagramSocket socket = new DatagramSocket();//数据报socket
    //2. 建立包
    String msg = "hello UDP!";
    //发送给谁
    InetAddress local = InetAddress.getByName("localhost");
    int port = 9999;
    DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,local,port);//发送的时候要知道对面的ip和端口
    //3. 发送包
    socket.send(packet);
    
    socket.close();
    

2.服务端

  1. 等待客户端连接

  2. 创建数据报socket,同时开放端口

  3. 接收数据包

  • 建立缓冲区
  • 建立数据包,填充缓冲区
  • 接收数据包
  1. 输出数据包

  2. 关闭

    //创建socket,同时开放端口
    DatagramSocket socket = new DatagramSocket(9999);//参数是开放端口,只有在等待接受时需要
    //接受数据包
    byte[] bytes = new byte[1024];
    DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);//接受的时候不需要知道ip和端口
    
    socket.receive(packet);
    System.out.println(packet.getAddress().getHostName());
    System.out.println(new String(packet.getData()));
    
    socket.close();
    

3.循环进行

1.发送方

//1.创建数据报socket,并开放等待端口
DatagramSocket socket = new DatagramSocket(8888);

while(true){
    //2.建立字符读取流,从控制台接收
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    //3.将字符读取流的信息读取并转化为String
    String data = reader.readLine();

    //4.将String转为字符数组
    byte[] datas = data.getBytes();

    //5.将信息放入包中,放入字符,长度,目标IP和端口
    DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));
    socket.send(packet);

    if(data.equals("bye")){
        System.out.println("成功断开");
        break;
    }
}

socket.close();

2.接收方

//1. 创建数据报socket
DatagramSocket socket = new DatagramSocket(6666);


//2.无限等待接收
while (true) {

    //3.创建容器,用于放在数据包里接受
    byte[] container = new byte[1024];

    //数据包,只需要知道容器,和长度,相当于把快递接过来
    DatagramPacket packet = new DatagramPacket(container, 0, container.length);

    //4.接收,带回家
    socket.receive(packet);

    //注意,在这里接受的字符串因为长度锁定,所以不会正确比较,正确做法是将String的长度变成包收发数据的长度
    String receiveData = new String(packet.getData(), 0, packet.getLength());

    System.out.println(receiveData);//彻底拆包

    //6.判断是否结束

    if(receiveData.equals("bye")){
        System.out.println("成功断开");
        break;
    }
}

socket.close();

醉后不知天在水,满船清梦压星河