栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

基于TCP协议的Socket通信 JAVA多线程版(详细注释)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于TCP协议的Socket通信 JAVA多线程版(详细注释)

文章目录
    • TCP连接流程
    • 代码实战
      • 1. 目录结构
      • 2. 代码详解
        • 客户端代码 Client.java
        • 服务端代码 Server.java
        • 服务端多线程代码 ServerThread.java
      • 3. 结果展示

TCP连接流程


整个的连接流程如图所示,需要注意的是服务器端创建了两个socket,一个用于监听,一个用于接受具体的连接,而本文所主要采用的多线程客户-服务器socket通信,主要是将连接成功的socket交给不同的线程去处理,来执行不同的数据传输任务(图中蓝色部分),从而服务器可以继续监听来自其他客户端的连接不被阻塞住。

代码实战 1. 目录结构

2. 代码详解 客户端代码 Client.java
package myTCP;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
public class Client {    
    public static void main(String[] args) {        
        try{    
                // 创建 socket 与 localhost:8888(服务器) 建立连接
                Socket socket = new Socket("localhost", 8888);
                

                //注意以上连接方式和流程图不符
                //我们没有绑定客户端的本地端口,如果我们想绑定可以按照如下方式:
                //Socket socket=new Socket();
                //socket.bind(new InetSocketAddress(3000)); // 绑定了本地的3000端口
                //socket.connect(new InetSocketAddress("localhost", 8888));

                // 获取socket输出流(这里的输出是相对与客户端的也就是会输出到服务器)
                OutputStream outStream = socket.getOutputStream();
                // PrintWriter 以便以我们可以传入更多类型的数据
                PrintWriter printWriter = new PrintWriter(outStream);
                // 要传输的内容
                printWriter.println("userName: zxd passWord: zxd");
                // 刷新缓冲区, 以免缓冲区残留数据
                printWriter.flush();
                // 关闭输出流,代表客户端向服务器传输数据结束
                socket.shutdownOutput();
                
                // 获取socket输入流(这里的输出是相对与客户端的也就是会会接受服务器的输出)
                InputStream is = socket.getInputStream();
                // InputStreamReader 使得我们可以按不同编码方式读取
                InputStreamReader isr = new InputStreamReader(is);
                // 读缓冲区
                BufferedReader br = new BufferedReader(isr);
                // 定义接收数据格式
                String data = null;
                // 按行接收并打印结果
                while ((data = br.readLine()) != null) {
                    System.out.println("服务器返回的数据为:"+data);
                }            
                // 收发数据均已经结束 关闭socket
                socket.close();
            // 以下是必须进行捕获的异常
            } catch (UnknownHostException e){
                e.printStackTrace();        
            } catch (IOException e) {
                e.printStackTrace();        
            }    
    }
}
服务端代码 Server.java
package myTCP;
import java.net.ServerSocket;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
public class Server {    
    public static void main(String[] args) {
        try {
            // 定义监听socket 监听8888端口
            ServerSocket serverSocket =  new ServerSocket(8888);
            // 定义连接socket
            Socket socket = null;
            // 记录客户端的连接次数
            int count = 0;
            // 此时服务器已经准备好 打印log
            System.out.println("Sever Start!!");
            // 循环监听
            while (true) {
                // 连接socket建立成功, 
                socket = serverSocket.accept();
                // 将具体的数据传输任务丢给连接处理线程 
                Thread thread = new Thread(new ServerThread(socket));
                // 线程开始运行
                thread.start();
                // 连接数加一
                count++;
                // 实时打印log 显示连接数
                System.out.println("The num of connection :" + count);
                // 获取连接地址
                InetAddress address = socket.getInetAddress();
                // 实时打印log 显示当前连接的客户端地址
                System.out.println("The address of client now:" + 
                address.getHostAddress());
            }
        // 服务器的连接不用关闭 
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
服务端多线程代码 ServerThread.java
package myTCP;
import java.net.Socket;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
//  线程类实现runnable接口
public class ServerThread implements Runnable{
    // 对应连接socket
    Socket socket = null;
    // 构造函数初始化连接socket
    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 data = null;
            
            // 按行接收,并返回数据给客户端
            while((data = br.readLine()) != null) {
                System.out.println("The client seed data:" + data);
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.println("Access tcpServer Successfully!");
                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 e) {
                e.printStackTrace();
            }
        }
    }
}
3. 结果展示
  • 先运行Server.java 文件

  • 在运行客户端文件

  • 此时服务端会打印log

  • 保持服务端开启,再次运行客户端程序

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/590620.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号