Java多线程实现多客户端的通信

title: Java多线程实现多客户端的通信
date: 2019-05-05 12:50:00

Java多线程实现多客户端的通信

昨天学了Java中网络支持Socket应用,写了一个基于TCP通信的简陋的登录案例,代码如下:

服务器端:

package com.youdian.singinscoket;
​
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
​
/***
 * 基于TCP协议的Socket,实现用户登录
 * 服务器端
 * @author hkq
 *
 */
public class Servert {
    public static void main(String[] args) {
    try {
        //1.创建一个服务器端的Socket,即ServerSocket,指定绑定的端口,并监听此端口
        ServerSocket serverSocket=new ServerSocket(8088);
        //2.调用accept()方法开始监听.
        System.out.println("服务器端启动,等待客户端连接");
        Socket socket= serverSocket.accept();
        //3.获取字节输入流,并读取客户端信息
        InputStream is=socket.getInputStream();
        //4.将字节流装换为字符流,好处是提高读取的效率
        InputStreamReader isr=new InputStreamReader(is);
        //5.搭配使用,为字符输入流添加缓冲
        BufferedReader br=new BufferedReader(isr);
        //6.定义String类型的info,循环读取客户端信息并在控制台输出
        String info=null;
        while ((info=br.readLine())!=null) {
            System.out.println("服务器端接收到客户端数据为:"+info);  
        }
        //7.关闭socket输入流
        socket.shutdownInput();
        //8.获取输出流,响应客户端的请求
        OutputStream os =socket.getOutputStream();
        //将字节输出流转换为打印输出流
        PrintWriter pw=new PrintWriter(os);
        //服务器端向客户端发送响应信息
        pw.write("登录成功,欢迎你");
        //调用flush()方法刷新缓存
        pw.flush();
        //9.关闭资源
        pw.close();
        os.close();
        br.close();
        isr.close();
        is.close();
        socket.close();
        serverSocket.close();
        } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
​
    }
​
}
客户端:
package com.youdian.singinscoket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
​
/***
 * 客户端
 * @author hkq
 *
 */
public class Client {
​
    public static void main(String[] args) {
        try {
            //1.创建客户端Socket,指定`服务器地址和端口
            Socket socket=new Socket("127.0.0.1", 8088);
            //2.连接建立后,通过获取字节输出流读取服务器发送信息
            OutputStream os =socket.getOutputStream();
            //将字节输出流转换为打印输出流
            PrintWriter pw=new PrintWriter(os);
            //向服务器端发送用户信息请求
            pw.write("用户名: admin;密码: 123");
            //刷新缓存
            pw.flush();
            //关闭scoket的输出流
            socket.shutdownOutput();
            //获取输入流,并读取服务器端的响应信息
            InputStream is=socket.getInputStream();
            //将字节流装换为字符流,好处是提高读取的效率
            InputStreamReader isr=new InputStreamReader(is);
            //搭配使用,为字符输入流添加缓冲
            BufferedReader br=new BufferedReader(isr);
            //定义String类型的info,循环读取服务器信息响应并在控制台输出
            String info=null;
            while ((info=br.readLine())!=null) {
                System.out.println("客户端接收到服务器端数据为:"+info);  
            }
        
            //关闭所有资源
            br.close();
            is.close();
            pw.close();
            os.close();
            socket.close();
            } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
​
    }
​
}
​

运行的时候,一定是服务器端的代码先运行,因为客户端的代码先运行会因为找不到服务器端的出现错误提示.....

其实,实际开发中,不可能如上述代码实现服务器端和客户端的通信,因为这个只是点对点的通信方式,不可能为了一个客户端通信单独用一个服务器(有钱任性的,当我没说哈!!!土豪交个朋友!)好了,言归正传,使用多线程实现多客户端的通信,下面直接在上述代码上更改......

创建一个serverThread类继承Thread类,用来处理服务器线程,代码如下:
 

package com.youdian.singinscoket;
/***
* 服务器线程处理类
* @author hkq
*
*/
​
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
​
public class ServerThread extends Thread {
//和本线程相关的Socket
Socket socket=null;
​
public ServerThread(Socket socket) {
this.socket=socket;
}
//线程执行的操作,响应客户端的请求
public void run() {
InputStream is=null;
InputStreamReader isr =null;
BufferedReader br=null;
PrintWriter pw=null;
OutputStream os=null;
try { 
      //获取字节输入流,并读取客户端信息
is=socket.getInputStream();
//将字节流装换为字符流,好处是提高读取的效率
   isr=new InputStreamReader(is);
//5.搭配使用,为字符输入流添加缓冲
br=new BufferedReader(isr);
//6.定义String类型的info,循环读取客户端信息并在控制台输出
String info=null;

while ((info=br.readLine())!=null) {
System.out.println("服务器端接收到客户端数据为:"+info); 
}

//7.关闭socket输入流
socket.shutdownInput();
//8.获取输出流,响应客户端的请求
   os =socket.getOutputStream();
//将字节输出流转换为打印输出流
pw=new PrintWriter(os);
//服务器端向客户端发送响应信息
pw.write("登录成功,欢迎你");
//调用flush()方法刷新缓存
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//如果为空,关闭资源
if (pw!=null) 
pw.close();
if(os!=null)
 os.close();
if(br!=null)
 br.close();
if (isr!=null) 
 isr.close();
if(is!=null)
 is.close();
if(socket!=null)
 socket.close();
} catch (Exception e2) {
}
}

}
}
​

服务器端代码修改为,如下:

package com.youdian.singinscoket;
​
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
​
/***
 * 基于TCP协议的Socket,实现用户登录
 * 服务器端
 * @author hkq
 *
 */
public class Servert {
    public static void main(String[] args) {
    try {
        //1.创建一个服务器端的Socket,即ServerSocket,指定绑定的端口,并监听此端口
        ServerSocket serverSocket=new ServerSocket(8088);
        Socket socket=null;
        int count=0;
        System.out.println("服务器端启动,等待客户端连接");
        //使用一个死循环监听
        while(true) {
            //调用accept()方法开始监听,等待客户端的连接
            socket= serverSocket.accept();
            //创建一个新的线程
            ServerThread serverThread=new ServerThread(socket);
            //启动线程
            serverThread.start();
            count++;//统计客户端数量
            System.out.println("当前连接客户端数量:"+count);
        }
        
        } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
​
    }
​
}
​

客户端不变,多创建一个客户端类

package com.youdian.singinscoket;
​
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
​
/***
 * 客户端
 * @author hkq
 *
 */
public class Client2 {
​
    public static void main(String[] args) {
        try {
            //1.创建客户端Socket,指定`服务器地址和端口
            Socket socket=new Socket("127.0.0.1", 8088);
            //2.连接建立后,通过获取字节输出流读取服务器发送信息
            OutputStream os =socket.getOutputStream();
            //将字节输出流转换为打印输出流
            PrintWriter pw=new PrintWriter(os);
            //向服务器端发送用户信息请求
            pw.write("用户名: root;密码:5618 ");
            //刷新缓存
            pw.flush();
            //关闭scoket的输出流
            socket.shutdownOutput();
            //获取输入流,并读取服务器端的响应信息
            InputStream is=socket.getInputStream();
            //将字节流装换为字符流,好处是提高读取的效率
            InputStreamReader isr=new InputStreamReader(is);
            //搭配使用,为字符输入流添加缓冲
            BufferedReader br=new BufferedReader(isr);
            //定义String类型的info,循环读取服务器信息响应并在控制台输出
            String info=null;
            while ((info=br.readLine())!=null) {
                System.out.println("客户端接收到服务器端数据为:"+info);  
            }
        
            //关闭所有资源
            br.close();
            is.close();
            pw.close();
            os.close();
            socket.close();
            } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
​
    }
​
}
​

代码运行结果:

多线程改造完成,实现多客户端与服务器端通信...多线程的本质就是让程序运行占用的资源最优化处理

你可能感兴趣的:(java)