美文网首页
基于socket的进程通信

基于socket的进程通信

作者: 顾庭燎 | 来源:发表于2019-04-01 19:42 被阅读0次
    • 实现目标

      • 实现服务端与客户端的连接
      • 实现多个客户端向服务端发送消息,并由服务端将消息发送给每个客户端
    • 涉及的Java类

      • java.net.ServerSocket 用于创建服务器端口
      • java.net.Socket 用于创建Socket
      • java.net.URLDecoder 用于在服务端将客户端传来的消息解码
      • java.util.ArrayList 用于动态存放多个不同的Socket
      • Java.util.scanner 用于从控制台读取输入
    • 具体实现思路

      • 服务端

        • 在主函数中建立一个端口用于监听客户端请求,端口大小可自行设置

          ServerSocket sock = new ServerSocket(1999)
          
        • 需要接受多个客户端的消息,因此需要和每个客户端建立唯一的Socket对用于通信,所以需要将新建的Socket存入动态容器ArrayList<Socket>中

          ArrayList<Socket> list = new ArrayList<Socket>()
          
        • 使用while循环,在while循环中调用ServerSocket的accept()方法等待客户端请求,当接受到请求时就将返回的Socket存入容器中,并新建一个线程(调用start函数)

          while(true) {
              Socket socket = sock.accept();
              list.add(socket);
              new MsgThread(socket, list).start();
          }
          
        • 在线程类中进行数据的读入和输出

        • 定义类的属性:Socket, ArrayList<Socket>,BufferedReader

        • 定义构造函数,将传入的参数赋给当前对象的属性,同时,通过Socket读取客户端的数据到BufferedReader对象

          BufferedReader bf = new BufferedReader(new   InputStreamReader(client.getInputStream));
          //这里需要用InputStreamReader类来包装client.getInputStream是为了将字节流转换成字符流
          
        • 重载run函数,将读取的消息发送给除当前socket对象外的其他客户端

          • 在这一步中的PrintWriter的使用要注意,一定要将自动刷新设置为true,否则消息就不能够即时传入到内存中,而是会等到程序结束时才传入,这个bug卡了我好久
        • 将消息解码后显示在控制台上

      • 客户端

        • 和服务端差不多的思路,主要是实现消息的读取和上传

        • 新建Socket,连接服务端

          Socket client = new Socket("127.000.001", 1999;
          
        • 读取Socket中的数据并显示在控制台上

        • 线程函数和服务端类似,无非是从控制台读取数据然后用getOutPutStream写入Socket中

    • 源码

      //服务端
      import java.io.*;
      import java.net.ServerSocket;
      import java.net.Socket;
      import java.net.URLDecoder;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Scanner;
      
      public class ChatServer {
          //SockerList用于保存当前连接的用户
          public static ArrayList<Socket> SocketList = new ArrayList<Socket>();
          public static void main(String[] args) throws IOException {
              //创建端口监听用户的请求
              ServerSocket sock = new ServerSocket(1999);
              System.out.println("服务启动....");
              //服务器循环接受来自用户端的请求
              while(true) {
                  //等待客户端的请求,捕获到请求后返会一个Socket
                  Socket socket = sock.accept();
                  System.out.println("服务连接....");
                  //将返回的Socket加入在线用户列表中
                  SocketList.add(socket);
                  System.out.println("当前有" + (SocketList.size()) + "个用户");
                  //创建一个新的线程,每个连接都会有自己独立的任务线程,用于实现接受和发送消息
                  new MsgThread(socket, SocketList).start();
              }
          }
      }
      
      //任务线程
      class MsgThread extends Thread {
          //定义单个用户连接的Socket
          Socket client;
          //定义用户组的Socket
          ArrayList<Socket> clients;
          //定义读入的数据
          BufferedReader br;
          //构造函数
          public MsgThread(Socket client, ArrayList<Socket> clients) throws IOException {
              //调用父类的构造函数
              super();
              //使用传入的参数初始化
              this.client = client;
              this.clients = clients;
              //将当前用户的输入缓存
              br = new BufferedReader(new InputStreamReader(this.client.getInputStream()));
          }
          //重载run()函数,将接受到的用户信息发送给其他用户
          @Override
          public void run() {
              try {
                  String content = null;
                  while(true) {
                      //从某个客户端获取信息
                      if ((content = br.readLine()) != null) {
                          //将消息发送给其他各个客户端
                          for (Socket socket:clients) {
                              //去掉自身客户端
                              if (socket != client) {
                                  //将消息写入socket的缓存区,设置为自动刷新
                                  PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
                                  pw.println(content);
                              }
                          }
                          content = URLDecoder.decode(content, "UTF-8");
                          System.out.println(content);
                      }
                  }
              }
              catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      
      
      //客户端
      import java.io.*;
      import java.net.*;
      
      public class ChatClient {
      
          public static void main(String[] args) throws Exception {
              //连接服务端
              Socket client = new Socket("127.0.0.1", 1999);
              System.out.println("服务器已连接");
              //新建线程
              new MsgThread(client).start();
              //获取输入
              InputStream in = client.getInputStream();
              BufferedReader bf = new BufferedReader(new InputStreamReader(in));
              while (true) {
                  String msg = bf.readLine();
                  //对收到的信息进行解码
                  msg=URLDecoder.decode(msg, "UTF-8");
                  System.out.println(msg);
              }
          }
      }
      
      class MsgThread extends Thread {
          Socket client;
          String hostname;
          public MsgThread(Socket client) {
              super();
              this.client = client;
              try {
                  //获取本计算机名称
                  InetAddress addr = InetAddress.getLocalHost();
                  hostname =addr.getHostName().toString();
              } catch (UnknownHostException e1) {
                  e1.printStackTrace();
              }
          }
          //发送消息
          @Override
          public void run() {
              try {
                  //读取控制台输入
                  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                  //将客户端输出流存到pw中
                  PrintWriter pw = new PrintWriter(client.getOutputStream(),true);
                  while (true) {
                      String msg = br.readLine();
                      //对发出的消息进行编码
                      msg = URLEncoder.encode(hostname + "说:"+ msg, "UTF-8");
                      pw.println(msg);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      
      
      

    相关文章

      网友评论

          本文标题:基于socket的进程通信

          本文链接:https://www.haomeiwen.com/subject/zzebbqtx.html