简易网络聊天编程

 

1、网络通信两要素

  1. IP地址、端口

    • 6ipconfig->获取本机地址;

    • ping www.baidu.com->获取对方IP地址

  2. 网络通信协议--TCP&UDP

 

2、IP地址

  • IPv4:地址是4位字节,截至2011年已经分完,北美大概30亿,亚洲4亿;

  • IPv6:地址是8位字节,尚未完成布置

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

    public class TestNetAdress {
       public static void main(String[] args) throws UnknownHostException {
           //查询本机IP地址
           InetAddress inetAddress1 = InetAddress.getByName("192.168.0.127");
           System.out.println(inetAddress1);
           InetAddress inetAddress2 = InetAddress.getByName("localhost");
           System.out.println(inetAddress2);
           InetAddress inetAddress3 = InetAddress.getLocalHost();
           System.out.println(inetAddress3);
           //查询网站IP地址
           InetAddress inetAddress4 = InetAddress.getByName("www.baidu.com");
           System.out.println(inetAddress4);
           //常用的方法
           System.out.println(inetAddress4.getAddress());//返回的是byte
           System.out.println(inetAddress4.getHostAddress());//返回的是域名地址
           System.out.println(inetAddress4.getHostName());//返回的是域名
           System.out.println(inetAddress4.getCanonicalHostName());//返回规范名字
      }
    }

     

3、端口

  • 端口:代表计算机上某一进程,被规定0~65535,查看端口:netstat -ano

    • TCP、UDP:65535*2,TCP:80,UDP:80,单个协议下,端口号不能冲突

  • 端口分类:

  • netstat -ano  #查看端口
    netstat -ano|findstr "9048" #查看指定端口,双引号前面有空格
    tasklist|findstr "9504"  #查看指定端口
    ctrl + shift + esc
    //创建地址和端口
    import java.net.InetSocketAddress;

    public class TestInetSocketsAddresses {
       public static void main(String[] args) {
           InetSocketAddress socketAddress
                   = new InetSocketAddress("192.168.0.127", 8080);//创建地址和端口
           InetSocketAddress socketAddress2
                   = new InetSocketAddress("localhost", 8080);
           System.out.println(socketAddress);
           System.out.println(socketAddress2);

           System.out.println(socketAddress2.getAddress());//获取用户地址
           System.out.println(socketAddress2.getHostName());//获取用户名
           System.out.println(socketAddress2.getPort());//获取端口

      }
    }

     

4、通信协议

  • TCP对比UDP

    • TCP:类似打电话;连接稳定,三次握手,四次挥手;客户端和服务器;连接稳定,释放连接,效率低。

    • UDP:类似发短信,不连接,不稳定,只是把包丢出去就不管了;

  •  

5、TCP实现聊天

  • TCP

    • TCP类似打电话,连接稳定,三次握手,四次挥手

    • UDP类似发短信,不连接,不稳定,只是把包丢出去就不管了

  • package network.tcptalk;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    //客户端----------------------------------
    public class TcpClientDemo01 {
       public static void main(String[] args) {
           Socket socket = null;
           OutputStream os = null;
           try {
               //客户端要知道服务端的地址,端口号
               InetAddress serverIP = InetAddress.getByName("192.168.0.107");//本机的地址ipconfig
               int port = 9999;
               //创建一个socket连接
               socket = new Socket(serverIP, port);
               //发送消息流IO
               os = socket.getOutputStream();//用于将字节写入此套接字的输出流。
               os.write("你好呀!".getBytes());//字符串转为字节,再写入输出流
          } catch (Exception e) {
               e.printStackTrace();
          }finally {
               if(os!=null){//确保程序运行
                   try {
                       os.close();
                  } catch (IOException e) {
                       e.printStackTrace();
                  }
              }
               if(socket!=null){//确保程序运行
                   try {
                       socket.close();
                  } catch (IOException e) {
                       e.printStackTrace();
                  }
              }
          }
      }
    }
    package network.tcptalk;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    //服务端-------------------------------------
    public class TcpServerDemo01 {
       public static void main(String[] args) {
           ServerSocket serversocket = null;
           Socket socket = null;
           InputStream is = null;
           ByteArrayOutputStream baos =null;
           try {
               //1、服务端先有一个地址
               serversocket = new ServerSocket(9999);
               //2、等待连接
               socket = serversocket.accept();
               //读取客户端消息
               is = socket.getInputStream();
               //3、管道流,read读输入管道->存入buffer缓存->write写入输出管道
               baos = new ByteArrayOutputStream();
               byte[] buffer = new byte[1024];//字节缓存容器
               int len;
               while((len= is.read(buffer))!=-1){//从输入流读取字节存入buffer,再判断是否读完输入流,读完输入流则返回-1
                   baos.write(buffer,0,len);//将buffer里面的字节写入输出管道
              }
               System.out.println(baos.toString());//将字节转成字符串打印输出


          } catch (IOException e) {
               e.printStackTrace();
          }finally {
               if(baos!=null){//抛出异常,确保程序不崩溃不为空才需要主动关闭,为空就自动关闭了
                   try {
                       baos.close();
                  } catch (IOException e) {
                       e.printStackTrace();
                  }
              }
               if(is!=null){
                   try {
                       is.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();
                  }
              }

          }
      }
    }

     

6、文件传输

  • //客户端
    import java.io.*;
    import java.net.InetAddress;
    import java.net.Socket;

    public class TcpFileClient {
       public static void main(String[] args) throws Exception {
           //获取服务器端口地址
           InetAddress serverIP = InetAddress.getByName("192.168.0.107");
           int port = 9900;
           //创建一个socket连接
           Socket socket = new Socket(serverIP,port);
           //创建一个输出流
           OutputStream os = socket.getOutputStream();
           //创建文件输出流,图片文件要放在根目录
           FileInputStream fis = new FileInputStream(new File("Guilinlandscape.jpg"));

           //这一段保证数据不出错,不出现乱码
           int len;
           byte[] buffer = new byte[1024];
           while((len=fis.read(buffer))!=-1){
              os.write(buffer,0,len);
          }
           //告诉接口我已经输出完毕
           socket.shutdownOutput();
           //接收服务器传过来的消息
           InputStream is = socket.getInputStream();
           ByteArrayOutputStream baos = new ByteArrayOutputStream();
           int len2;
           byte[] buffer2 = new byte[1024];
           while((len2=is.read(buffer2))!=-1){
               baos.write(buffer2,0,len2);
          }
           System.out.println(baos.toString());


           baos.close();
           is.close();
           fis.close();
           os.close();
           socket.close();

      }
    }
  • //服务端
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;

    public class TcpFileServer {
       public static void main(String[] args) throws IOException {
           //创建服务器地址端口
           ServerSocket serversocket = new ServerSocket(9900);
           //等待连接
           Socket socket = serversocket.accept();
           //创建输入流,这一段是防止传输的数据出错
           InputStream is = socket.getInputStream();
           FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
           int len;
           byte[] buffer = new byte[1024];
           while((len=is.read(buffer))!=-1){
               fos.write(buffer,0,len);
          }
           //返回文件接收成功给客户端
           OutputStream os = socket.getOutputStream();
           os.write("文件传输完毕!".getBytes());

           fos.close();
           is.close();
           socket.close();
           serversocket.close();
      }
    }

     

7、UDP聊天

  • //发送端
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.*;

    public class UdpChatSender {
       public static void main(String[] args) throws Exception {
           //建立端口
           DatagramSocket socket = new DatagramSocket(8888);
           InetSocketAddress localhost = new InetSocketAddress("localhost", 6666);
           //准备发送数据,读到的是字符串
           while(true){
               BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
               String data = reader.readLine();
               byte[] sendData = data.getBytes();
               //建立发送包,
               DatagramPacket packet = new DatagramPacket(sendData,0,sendData.length,localhost);
               //发送包
               socket.send(packet);
               if(data.equals("bye")){
                   break;
              }
          }
           socket.close();
      }
    }

     

  • //接收端
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;

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

           while(true){
               byte[] container = new byte[1024];
               DatagramPacket packet = new DatagramPacket(container,0,container.length);
               socket.receive(packet);

               //打印出接收到的数据
               byte[] data = packet.getData();
               String dataToString = new String(data,0, data.length);

               if(dataToString.equals("bye")){//有问题
                   System.out.println("结束!");
                   break;
              }
               System.out.println(dataToString);
          }

           socket.close();
      }
    }

     

8、UDP多线程聊天

  • //发送端
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetSocketAddress;
    import java.net.SocketException;

    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 (SocketException e) {
               e.printStackTrace();
          }
      }

       @Override
       public void run() {
           //建立端口
           try {
               //准备发送数据,读到的是字符串
               while(true){
                   String data = reader.readLine();
                   byte[] sendData = data.getBytes();
                   //建立发送包,
                   DatagramPacket packet = new DatagramPacket
                          (sendData,0,sendData.length,new InetSocketAddress(this.toIp,this.toPort));
                   //发送包
                   socket.send(packet);
                   if(data.equals("bye")){
                       break;
                  }
              }
               socket.close();
          } catch (Exception e) {
               e.printStackTrace();
          }

      }
    }

  • //接收端
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;

    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 {
               socket = new DatagramSocket(port);
          } catch (SocketException e) {
               e.printStackTrace();
          }
      }

       @Override
       public void run() {
           while(true){

               try {
                   byte[] container = new byte[1024];
                   DatagramPacket packet = new                                                                 DatagramPacket(container,0,container.length);
                   socket.receive(packet);
                   byte[] data = packet.getData();
                   String dataToString = new String(data,0, data.length);
                   //判断退出聊天
                   if(dataToString.equals("bye")){
                       System.out.println("结束!");
                       break;
                  }
                   System.out.println(msgFrom+":"+dataToString);
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           socket.close();
      }
    }
    //聊天用户二
    public class TalkTalkerTwo {
       public static void main(String[] args) {
            new Thread(new TalkSend(5555,"localhost",6666)).start();
            new Thread(new TalkReceive(8888,"One")).start();
      }
    }
    //聊天用户一
    public class TalkTalkerOne {
       public static void main(String[] args) {
           new Thread(new TalkSend(4444,"localhost",8888)).start();
           new Thread(new TalkReceive(6666,"Two")).start();
      }
    }

     

  •  

 

posted on 2021-03-30 15:38  唐唐唐11  阅读(144)  评论(0)    收藏  举报