Java网络编程-服务端程序实现

简介: Java网络编程-服务端程序实现

 最近学习了Java的net包,看了网上的开源代码,整理了一部分服务端代码,实现了消息监听,直接上代码。

一。新建了一个消息类,用于存储消息进行传输

package com.xing.studyTest.net.im.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
/**
 *  消息信息
 * @author xinghua
 *
 */
public class MessageBean implements Serializable{
  private static final long serialVersionUID = 1L;
  private int type; // 1私聊 0上下线更新 -1下线请求 2请求发送文件 3.确定接收文件
  private HashSet<String> clients; // 存放选中的客户
  private HashSet<String> to;//
  public HashMap<String, MessageBean> onlines;//
  private String info;//信息
  private String timer;//时间
  private String name;//昵称
  private String fileName;//文件名
  private int size;//文件大小
  private String ip;//IP
  private int port;//端口
  public int getSize() {
    return size;
  }
  public void setSize(int size) {
    this.size = size;
  }
  public String getFileName() {
    return fileName;
  }
  public void setFileName(String fileName) {
    this.fileName = fileName;
  }
  public HashSet<String> getTo() {
    return to;
  }
  public void setTo(HashSet<String> to) {
    this.to = to;
  }
  public int getType() {
    return type;
  }
  public void setType(int type) {
    this.type = type;
  }
  public HashSet<String> getClients() {
    return clients;
  }
  public void setClients(HashSet<String> clients) {
    this.clients = clients;
  }
  public String getInfo() {
    return info;
  }
  public void setInfo(String info) {
    this.info = info;
  }
  public String getTimer() {
    return timer;
  }
  public void setTimer(String timer) {
    this.timer = timer;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getIp() {
    return ip;
  }
  public void setIp(String ip) {
    this.ip = ip;
  }
  public int getPort() {
    return port;
  }
  public void setPort(int port) {
    this.port = port;
  }
  public HashMap<String, MessageBean> getOnlines() {
    return onlines;
  }
  public void setOnlines(HashMap<String, MessageBean> onlines) {
    this.onlines = onlines;
  }
  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return " [type=" + type + ", clients=" + clients + ", to=" + to + ", onlines=" + onlines + ", info="
        + info + ", timer=" + timer + ", name=" + name + ", fileName=" + fileName + ", size=" + size + ", ip="
        + ip + ", port=" + port + "]";
  }
}

image.gif

二、因为要存储在线用户和用户连接信息,所以还需要个实体类

package com.xing.studyTest.net.im.model;
import java.io.Serializable;
import java.net.Socket;
/**
 *  连接信息
 * @author xinghua
 *
 */
public class SocketBean implements Serializable{
  private static final long serialVersionUID = 1L;
  private String name;//名称
  private Socket socket;//socket
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Socket getSocket() {
    return socket;
  }
  public void setSocket(Socket socket) {
    this.socket = socket;
  }
  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return "ServerBean [name=" + name + ", socket=" + socket + "]";
  }
}

image.gif

三,好了,接下来就是Server代码

package com.xing.studyTest.net.im.server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import com.xing.studyTest.net.im.model.MessageBean;
import com.xing.studyTest.net.im.model.SocketBean;
/**
 *  
 * @author xinghua
 *
 */
public class SocketServer {
  private static ServerSocket ss;//服务端服务对象
  public static HashMap<String, SocketBean> onlines;//存储上线的Socket信息
  //1.准备服务端对象及容器
  static {
    try {
      ss = new ServerSocket(8520);
      onlines = new HashMap<String, SocketBean>();//新建一个容器存放客户端连接信息
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  //2.多线程实现监听消息处理
  class CatClientThread extends Thread {
    private Socket socket;//链接
    private MessageBean messageBean;//消息
    private ObjectInputStream ois;//读取消息
    private ObjectOutputStream oos;//输出消息
    public CatClientThread(Socket socket) {
      this.socket = socket;
    }
    @Override
    public void run() {
      try {
        messageBean = (MessageBean)new ObjectInputStream(socket.getInputStream()).readObject();
        System.out.println("获取消息对象:"+messageBean);
        //根据请求类型进行不同的操作
        switch (messageBean.getType()) {
          case 0: {  // 上线 
            System.out.println("上线1.记录上线客户的用户名和端口,组装用户名和Socket连接,添加到容器中");
            SocketBean socketBean = new SocketBean();
            socketBean.setName(messageBean.getName());
            socketBean.setSocket(socket);
            onlines.put(messageBean.getName(), socketBean);//添加到onlines中
            System.out.println("上线2.已存储上线,开始准备发送消息给客户端");
            System.out.println("当前在线人数:【"+onlines.keySet().size()+"】个");
            MessageBean returnMessageBean = new MessageBean();
            returnMessageBean.setType(0);
            returnMessageBean.setInfo(messageBean.getTimer() + "  [ " + messageBean.getName() + " ]上线了");
            System.out.println("上线3.发送消息准备完毕,发送给全部用户:");
            System.out.println(onlines.keySet());
//            System.out.println(onlines.values());
            HashSet<String> set = new HashSet<String>();
            set.addAll(onlines.keySet());
            returnMessageBean.setClients(set);
            sendAll(returnMessageBean);
            System.out.println("上线4.发送有人上线消息给全部用户完毕");
            break;
          }
          case -1: { // 下线
//            try {
//              oos = new ObjectOutputStream(socket.getOutputStream());
//              oos.writeObject(messageBean);
//              oos.flush();
//            } catch (IOException e) {
//              e.printStackTrace();
//            }
            System.out.println("下线1.将用户从容器删除");
            onlines.remove(messageBean.getName());
            System.out.println("下线2.用户已移除,准备发送消息告诉所有人他下线了");
            MessageBean returnMessageBean = new MessageBean();
            returnMessageBean.setType(-1);
            returnMessageBean.setInfo(messageBean.getTimer() + "  [ " + messageBean.getName() + " ]下线了");
            System.out.println("下线3.发送消息准备完毕,发送给全部用户");
            sendAll(returnMessageBean);
            System.out.println("下线4.发送有人下线消息给全部用户完毕");
            break;
          }
          case 1: {  // 聊天
            System.out.println("聊天1.组装消息,准备给选中的用户发送");
            MessageBean returnMessageBean = new MessageBean();
            returnMessageBean.setType(1);
            returnMessageBean.setClients(messageBean.getClients());
            returnMessageBean.setName(messageBean.getName());//选中的用户昵称
            returnMessageBean.setInfo(messageBean.getInfo());//消息内容
            returnMessageBean.setTimer(messageBean.getTimer());//发送时间
            System.out.println("聊天2.组装消息准备完毕开始发送");
            System.out.println(returnMessageBean);
            sendMessage(returnMessageBean);
            System.out.println("聊天3.发送消息完毕");
            break;
          }
          case 2: {  // 请求接受文件
            break;
          }
          case 3: {  // 确定接收文件
            break;
          }
          default: {
            break;
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        close();
      }
    }
    // 向选中的用户发送数据
    private void sendMessage(MessageBean messageBean) {
      // 首先取得所有的values
      Set<String> cbs = onlines.keySet();
      Iterator<String> it = cbs.iterator();
      // 选中客户
      HashSet<String> clients = messageBean.getClients();
      while (it.hasNext()) {
        // 在线客户
        String client = it.next();
        // 选中的客户中若是在线的,就发送
        if (clients.contains(client)) {
          Socket c = onlines.get(client).getSocket();
          ObjectOutputStream oos;
          try {
            oos = new ObjectOutputStream(c.getOutputStream());
            oos.writeObject(messageBean);
            oos.flush();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
    /*
     *  向所有的用户发送数据
     */
    public void sendAll(MessageBean serverBean) {
      Collection<SocketBean> clients = onlines.values();
      Iterator<SocketBean> it = clients.iterator();
      ObjectOutputStream oos;
      while (it.hasNext()) {
        Socket c = it.next().getSocket();
        try {
          oos = new ObjectOutputStream(c.getOutputStream());
          oos.writeObject(serverBean);
          oos.flush();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    /*
     * 关闭Socket连接
     */
    private void close() {
      if (oos != null) {
        try {
          oos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (ois != null) {
        try {
          ois.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (socket != null) {
        try {
          socket.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
  /*
   *  循环调用监听与本Socket的连接信息,
   */
  public void start() {
    try {
      Executor executor = Executors.newFixedThreadPool(3);
      while (true) {
        String name = ss.getInetAddress().getHostName();
        System.out.println("启动服务器监听程序启动完成,快来给我发送消息把!:host:"+name+"port:"+ss.getLocalPort());
        Socket socket = ss.accept();
        name = socket.getInetAddress().getHostName();
        System.out.println("收到host:"+name+"port:"+socket.getPort()+"的消息处理开始");
        Long timeStart = System.currentTimeMillis();
        executor.execute(new CatClientThread(socket));
//        new CatClientThread(socket).start();
        System.out.println("收到host:"+name+"port:"+socket.getPort()+"的消息处理完毕,用时【"+(System.currentTimeMillis()-timeStart)+"】秒");
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  } 
}

image.gif

四、最后启动:

package com.xing.studyTest.net.im.main;
import com.xing.studyTest.net.im.server.SocketServer;
/**
 *  启动服务端
 * @author xinghua
 *
 */
public class ServerApplication {
  public static void main(String[] args) {
    new SocketServer().start();
  }
}

image.gif

五、此时就在监听 等待客户端发消息来连接了

image.gif编辑

六、简单的客户端搞个上线信息发送:

package com.xing.studyTest.net.im.main;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import com.xing.studyTest.net.im.model.MessageBean;
/**
 *  客户端
 * @author xinghua
 *
 */
public class ClientApplication2 {
  private static final String HOST = "localhost";//host
  private static final int PORT = 8520;//端口
  private static final String NAME = "雅楠";//host
  public static void main(String[] args) {
    Socket socket = null;
    DataInputStream dataInputStream = null;
    DataOutputStream dataOutputStream = null;
    try {
      Scanner input = new Scanner(System.in);
      System.out.println("请输入一个昵称");
      String name = input.nextLine();
      System.out.println("你的昵称是【"+name+"】,开始连接。。。");
      //上线
      MessageBean messageBean = new MessageBean();
      messageBean.setType(0);
      messageBean.setName(name);
      messageBean.setTimer(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
      socket = new Socket(HOST, PORT);
//      System.out.println("发起请求到->"+HOST+":"+PORT);
      ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
      oos.writeObject(messageBean);
      oos.flush();
      System.out.println("获取响应数据");
      MessageBean resMB = (MessageBean)new ObjectInputStream(socket.getInputStream()).readObject();
      System.out.println(resMB);
      System.out.println();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        if(dataInputStream != null){
          dataInputStream.close();
        }
        if(dataOutputStream != null){
        dataOutputStream.close();
        }
        if(socket != null){
          socket.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    } 
  }
}

image.gif

这是搞了个上线消息发送,并收到响应,客户端应该是不停的监听服务端发送消息,以实现聊天,还没写出来,下次再贴出来吧

image.gif编辑

好吧,自己发给自己了,啊哈哈哈哈

image.gif编辑

目录
相关文章
|
1天前
|
存储 Java 开发工具
【Java探索之旅】用面向对象的思维构建程序世界
【Java探索之旅】用面向对象的思维构建程序世界
9 0
|
1天前
|
小程序 Java 程序员
【Java探索之旅】我与Java的初相识(二):程序结构与运行关系和JDK,JRE,JVM的关系
【Java探索之旅】我与Java的初相识(二):程序结构与运行关系和JDK,JRE,JVM的关系
9 0
|
2天前
|
数据采集 存储 前端开发
Nutch库入门指南:利用Java编写采集程序,快速抓取北京车展重点车型
2024年北京车展凸显电动车全球热度,中国引领市场,展出117台全球首发车,包括30台跨国公司电动车。借助Nutch库抓取汽车网站数据,分析电动车市场趋势。通过配置代理和多线程爬虫,高效收集新车信息,助力理解市场动态,推动可持续交通发展。
Nutch库入门指南:利用Java编写采集程序,快速抓取北京车展重点车型
|
4天前
|
网络协议 Java 网络架构
Java基础教程(18)-Java中的网络编程
【4月更文挑战第18天】Java网络编程简化了底层协议处理,利用Java标准库接口进行TCP/IP通信。TCP协议提供可靠传输,常用于HTTP、SMTP等协议;UDP协议则更高效但不保证可靠性。在TCP编程中,ServerSocket用于监听客户端连接,Socket实现双进程间通信。UDP编程中,DatagramSocket处理无连接的数据报文。HTTP编程可以通过HttpURLConnection发送请求并接收响应。
|
7天前
|
Java
网页运行java程序cheerpj
网页运行java程序cheerpj
31 0
|
12天前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。
|
12天前
|
缓存 负载均衡 前端开发
构建高性能 Java Web 应用程序
【4月更文挑战第19天】构建高性能 Java Web 应用涉及数据库优化(合理设计、查询优化、性能调优)、缓存策略(服务器端缓存、HTTP 缓存)、代码优化(避免冗余查询、减少对象创建、有效使用线程)、异步处理(增强并发能力)、负载均衡(分发请求、提升可靠性)、性能测试与监控(发现瓶颈、实时问题)、前端优化(减少加载时间、优化资源)、服务器配置(硬件资源、系统优化)以及代码压缩和资源合并。综合运用这些技术,能显著提升应用性能和用户体验。
|
2月前
|
网络协议 算法 Java
|
4月前
|
Java 数据格式
最新Java基础系列课程--Day15-网络编程(三)
最新Java基础系列课程--Day15-网络编程
|
4月前
|
存储 网络协议 Java
最新Java基础系列课程--Day15-网络编程(二)
最新Java基础系列课程--Day15-网络编程