服务器使用多线程实现与多个客户端通讯实现与代码案例

1、应用场景

单实例的服务,实现与多个客户端进行通信。

2、实现方案

2.1、服务器端,创建ServerSocket对象,使用死循环调用accept()方法等待客户端请求建立连接;

2.2、客户端,创建Socket对象,请求与服务器建立连接;

2.3、服务端接受客户端的请求,并建立专线连接;底层是TCP的链接,即经历过三次握手;

2.4、建立连接的两个socket在一个单独的线程上对话,可以理解为一个专门的管道;客户端请求携带参数,服务器端对客户端作出响应,并返回参数;

2.5、服务器端单独开启新的线程,专门实现接受客户端请求和对客户端作出响应;优点:实现异步处理,提高了并发效率。

2.6、服务器端自动进入下一个循环,继续等待新的连接请求;

2.7、服务器端增加计数功能,实现累计客户端请求次数。

注意事项:

1、先启动服务端,再启动客户端,原因:客户端主动与服务器端建立连接。

2、服务器端的 ServerSocket 对象示例,不能执行.close();原因:要一直等待客户端请求建立连接。

3、代码实现

注明:代码参考慕课网汤小洋老师讲《Java socket 应用》。

3.1、服务器端

package com.liuxd.socket;


import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicInteger;

/*
 * 基于TCP协议的Socket通信,实现用户登陆
 * 服务器端
 */
public class Server {
    public static void main(String[] args) {
        try {
            //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
            ServerSocket serverSocket = new ServerSocket(8901);
            Socket socket = null;

            //记录客户端的数量
            AtomicInteger count = new AtomicInteger();
            System.out.println("***服务器即将启动,等待客户端的连接***");

            //循环监听等待客户端的连接
            while (true) {
                //调用accept()方法开始监听,等待客户端的连接
                socket = serverSocket.accept();
                //创建一个新的线程
                ServerThread serverThread = new ServerThread(socket);
                //启动线程
                serverThread.start();

                count.incrementAndGet();//统计客户端的数量
                System.out.println("客户端的数量:" + count.get());
                InetAddress address = socket.getInetAddress();
                System.out.println("当前客户端的IP:" + address.getHostAddress());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.2、服务器端处理接受参数与对客户端作出响应

package com.liuxd.socket;

/**
 * Created by Liuxd on 2018/9/15.
 */

import java.io.*;
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;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            //获取输入流,并读取客户端信息
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            String info;
            while ((info = br.readLine()) != null) {//循环读取客户端的信息
                System.out.println("我是服务器,客户端说:" + info);
            }
            socket.shutdownInput();//关闭输入流

            //获取输出流,响应客户端的请求
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.write("欢迎您!");
            pw.flush();//调用flush()方法将缓冲输出
        } catch (IOException e) {
            // TODO Auto-generated catch block
            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 (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.3、客户端

package com.liuxd.socket;

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;
import java.net.UnknownHostException;

/*
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        try {
            //1.创建客户端Socket,指定服务器地址和端口
            Socket socket = new Socket("127.0.0.1", 8901);

            //2.获取输出流,向服务器端发送信息
            OutputStream os = socket.getOutputStream();//字节输出流
            PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
            pw.write("用户名:alice;密码:789");
            pw.flush();
            socket.shutdownOutput();//关闭输出流

            //3.获取输入流,并读取服务器端的响应信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println("我是客户端,服务器说:" + info);
            }

            //4.关闭资源
            br.close();
            is.close();
            pw.close();
            os.close();
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春风化作秋雨

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值