zoukankan      html  css  js  c++  java
  • 使用多线程实现多个客户端与服务端通信1

    Server.java

    package socket;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;

    /**
    * 聊天室服务端
    * @author 小明
    *
    */
    public class Server {
    /**
    * 运行在服务端的ServerSocket主要有两个作用:
    * 1:向系统申请服务端口,客户端就是通过这个端口与服务端建立连接的。
    * 2:监听服务端口,一旦客户端与服务端建立连接,就会
    * 自动创建一个Socket,并通过该Socket与建立连接的
    * 客户端进行交互。
    *
    */
    private ServerSocket server;

    public Server()
    {
    try{
    /**
    * 实例化ServerSocket的同时要指定向系统申请的服务端口。注意,该端口
    * 不能与当前系统其它应用程序申请的端口号一致,
    * 否则会抛出端口被占用的异常。
    */
    System.out.println("正在启动服务端...");
    server = new ServerSocket(8088);
    System.out.println("服务端启动完毕!");
    }catch(Exception e){

    }
    }

    public void start()
    {
    try {
    while(true)
    {
    System.out.println("等待客户端连接");
    Socket socket = server.accept();
    //accept用来感知socket。
    System.out.println("一个客户端连接进去了。");

    ClientHandler hander = new ClientHandler(socket);
    Thread t1 = new Thread(hander);
    t1.start();
    }
    /**
    * 准备接受客户端连接
    *
    * 这是一个阻塞方法。
    *一旦调用accpet()方法,服务端阻塞在这里,等着客户端连接了。
    *这时当我们启动客户端时,客户端实例化socket,通过IP找到应用程序。
    *这时accpet()马上就会有反应。accpet()方法执行完就返回一个socket。
    *通过这个socket就可以与刚建立连接的这个客户端进行通讯了。
    *客户端创建一个socket,服务端通过accept()接收一个socket。
    *这时候就可以进行沟通了。
    * 需要处理异常。
    */
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    public static void main(String[] args) {
    Server server = new Server();
    server.start();
    }

    /**
    * 通过输入流读取远端计算机发送过来的信息时
    * br.readLine()方法对于不同系统的客户端断开时的反应不一样
    * windows的客户端断开时,会直接抛出异常
    * linux的客户端断开时,会返回null
    * 该线程任务是负责与指定的客户端进行交互
    * @author 小明
    *
    */
    private class ClientHandler implements Runnable{
    private Socket socket;
    private String host;
    //创建时需要将Socket传入,以便对该客户端交互
    public ClientHandler(Socket socket) {
    this.socket = socket;
    //通过socket获取远端的地址信息
    InetAddress address = socket.getInetAddress();
    host = address.getHostAddress();
    }
    @Override
    public void run() {
    try{
    System.out.println("进入了线程,现在正在调用run()方法");
    InputStream in = socket.getInputStream();
    InputStreamReader isr = new InputStreamReader(in);
    BufferedReader br = new BufferedReader(isr);
    String message = null;
    System.out.println("客户端地址是:" + host);
    //System.out.println("尝试输出br.readLine()" + br.readLine());
    System.out.println("while最上面的那条语句");

    while((message = br.readLine()) != null)
    {
    System.out.println("读取到了数据");
    System.out.println(host + "说" + message);
    System.out.println("一个客户端连接了");
    }
    if(message == null){
    System.out.println("message是空的");
    }
    br.close();
    }catch(IOException e){
    e.printStackTrace();
    }finally{
    //br.close();
    }
    }

    }

    }

    Client.java

    package socket;

    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.util.Scanner;

    /**
    * 聊天室客户端
    * @author 小明
    *
    */
    public class Client {
    /**
    * 套接字
    * 封装了TCP协议的通信细节,让我们可以简单地使用它完成TCP通讯
    * Socket连接后提供了两条流,通过两条流的读写操作完成与远端计算机的数据连接
    * 完成与远端计算机的数据交换。
    */
    private Socket socket;
    public Scanner reader;
    /**
    * 用来初始化客户端
    */
    public Client()
    {
    try {
    /**
    * 实例化Socket时需要传入两个参数:
    * 1:服务端的IP地址
    * 2:服务端的端口号
    * 通过IP地址可以找到服务端所在的计算机
    * 通过端口可以找到运行在服务端计算机上的
    * 服务端应用程序
    * 注意,实例化Socket的过程就是连接的过程,若
    * 连接失败就会抛出异常。
    */
    reader = new Scanner(System.in);

    System.out.println("正在连接服务端...");
    socket = new Socket("localhost", 8088);
    System.out.println("与服务端建立连接!");

    /**
    * 有两个参数,一个是IP地址,一个是端口号
    */
    /**
    * 所有应用程序在使用网络的时候都要和操作系统申请一个网络端口
    *
    */
    /**
    * 异常要我们自己进行处理,不要抛出
    */
    }catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    }

    /**
    * 写程序时不要过度依赖main方法
    * 客户端开始工作的方法
    */
    public void start()
    {
    try{
    //socket.getOutputStream();
    //打桩
    //可以找到代码错的地方。
    PrintWriter pw = new PrintWriter(
    new BufferedWriter(
    new OutputStreamWriter(
    socket.getOutputStream())), true);
    //pw.write("你好服务端");
    //使用上面这条语句是错的,要使用具有自动行刷新的方法
    //不要再下意识地写上面那条语句了
    // for(int i = 0; i < 10; i++){
    // pw.println("你好服务端!" + i);
    // }
    while(true)
    {
    String line = reader.nextLine();
    pw.println(line);
    }

    }catch(Exception e){
    e.printStackTrace();
    }
    }
    public static void main(String[] args) {
    Client client = new Client();
    client.start();
    }

    }

  • 相关阅读:
    矩阵分析及其在线性代数中的应用(3-4)
    矩阵分析及其在线性代数中的应用(1-2)
    信息检索的评价标准
    Converting Between Image Classes (matlab 中图像类之间的转换)
    Ubuntu 14.04,root the Nexus 7 (2013).
    ACM进阶计划
    matlab R2012a in ubuntu12.04
    人,绩效和职业道德
    运行及总结
    仓库管理 测试计划
  • 原文地址:https://www.cnblogs.com/liaoxiaolao/p/9597587.html
Copyright © 2011-2022 走看看