java网络编程基础---基于tcp的简单聊天系统

     2022-05-19     437

关键词:

实现思路:

    要实现消息的发送,客户端每次在连接服务器端时都需要告诉服务器自己的用户名,以便能够接收到发送给自己的消息。服务器端在接收到消息时,能够查到对应用户名的客户端,将消息发送给该客户端。

    服务端需要实现多个客户端的同时请求,因此需要使用多线程来处理客户端的请求。同时,它还需要保存一份用户名列表,以便在转发消息时能够查找到对应的用户。

    对于客户端来说,客户端需要能够随时收取服务器端转发来的消息,并能够随时通过键盘输入发送消息,因此它的读取消息和发送消息功能是并行的,需要独立的线程来实现。


实现过程:

    根据以上思路,客户端和服务端都需要独立的线程,因此分别包含了一个主程序和一个子线程类,共需要实现4个类。

    (1)、客户端主程序ChatClient.java

        该程序根据启动时输入的用户名参数,负责启动客户端的子线程,由子线程建立客户端和服务器的连接。在主线程中,需要循环读取键盘的输入,将输入的信息通过子线程发送给服务器,交由服务器来转发该消息给客户端。

    (2)、客户端子线程ClientThread.java

        该线程封装了客户端和服务器的所有操作。

        a、在构造函数中,根据用户名创建与服务端的连接,然后发送用户名给服务端进行注册

        b、在线程函数中,循环读取服务端发送的消息,并显示的控制台

        c、还应有一个发送消息的函数,外部的主线程在接收到键盘输入后,调用该函数给服务端发送消息

        d、关闭函数:在客户端输入bye命令后,关闭客户端和服务端连接。

    (3)、服务端主程序ChatServer.java

        该类负责启动服务器,并负责监听客户端的请求,在接收到新的用户端后,交给子线程处理。

    (4)、服务端子线程ServerThread.java

        该线程负责处理客户端的输入输出和消息转发任务,因此需要包含以下功能

            a、在构造函数中,建立与客户端的输入输出流,并在第一次建立连接时读取客户端发送的用户名,并将该用户添加到用户列表中。

            b、在主线程函数中,读取客户端的输入数据,如果发送的消息时bye,则推出监听关闭该客户端,否则根据命令格式进行解析。冒号(:)前的部分为用户名,根据该用户名在客户端列表中找到对应的客户端处理线程,发送数据给客户端

            c、发送数据函数:在收到用户消息进行转发时调用

参考样例

1、客户端

package org.test.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author kucs
 * 客户端主程序
 * 负责调用子线程创建客户端
 * 监听键盘输入
 * 根据系统启动参数取得用户名
 * 调用子线程创建该用户的客户端线程并启动
 */
public class ChatClient {

    public static void main(String[] args) {
        
        try {
            ClientThread client = new ClientThread(args[0]);
            client.start();
            
            //输入输出流
            BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
            //循环读取键盘输入
            String readLine;
            while((readLine = sin.readLine()) != null){
                if(readLine.equals("bye")){
                    client.close();
                    System.exit(0);
                }
                client.send(readLine);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

2、客户端线程

package org.test.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @author kucs
 * 
 * 受主线程委托,来创建与服务端的连接
 * 监听服务端的消息
 * 负责发送消息给服务端
 */
public class ClientThread extends Thread {
    Socket socket;        //socket对象
    BufferedReader is;    //输入流
    PrintWriter os;        //输出流
    
    //启动客户端
    public ClientThread(String userName) {
        //连接服务器
        try {
            socket = new Socket("127.0.0.1",12345);
            
            //输入输出流
            is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            os = new PrintWriter(socket.getOutputStream());
            
            //发送用户名
            os.println(userName);
            os.flush();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    @Override
    public void run() {
        try {
            // TODO 循环读取服务端转发的消息
            String readLine;
            while((readLine = is.readLine()) != null){
                System.out.println(readLine);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            // TODO 关闭客户端
            is.close();
            os.close();
            
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void send(String readLine) {
        // TODO 发送消息
        os.print(readLine);
        os.flush();
    }

}

3、服务端

package org.test.example;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;

/**
 * @author kucs
 *
 */
public class ChatServer {
    public static void main(String[] args) {
        ServerSocket server = null;
        try {
            // TODO 启动服务端
            server = new ServerSocket(12345);
            System.out.println("服务端启动:"+
                    server.getInetAddress().getHostAddress()+":"+
                    server.getLocalPort());
            
            //客户端列表
            Hashtable<String, ServerThread> clientList = new Hashtable<String, ServerThread>();
            
            //监听客户端
            while(true){
                Socket socket = server.accept();
                //启动服务端处理线程
                new ServerThread(socket,clientList).start();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally{
            try {
                server.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

4、服务端线程

package org.test.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Hashtable;

public class ServerThread extends Thread {
    
    Socket socket;                                //Socket对象
    BufferedReader is;                            //输入流
    PrintWriter os;                                //输出流
    Hashtable<String, ServerThread> clientList;    //客户端列表
    String userName;                            //用户名
    public ServerThread(Socket socket, Hashtable<String, ServerThread> clientList) {
        this.socket = socket;
        this.clientList = clientList;
        
        try {
            //输入输出流
            is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            os = new PrintWriter(socket.getOutputStream());
            
            //读取用户名
            this.userName = is.readLine();
            clientList.put(userName, this);
            
            //显示连接信息
            System.out.println(userName+"连接:"
                    + socket.getInetAddress().getHostAddress()+":"
                    + socket.getLocalPort());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        // TODO 循环处理客户端输入
        try {
            String line;
            while((line = is.readLine()) != null){
                //用户输入信息
                System.out.println(userName + "发给"+line);
                if(line.equals("bye")){
                    break;
                }else{
                    //转发消息给客户端
                    String[] arr = line.split(":");
                    if(arr.length == 2){
                        if(clientList.containsKey(arr[0])){
                            clientList.get(arr[0]).send(userName+":"+arr[1]);
                        }
                    }
                }
            }
            is.close();
            os.close();
            
            //关闭客户端
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    private void send(String msg) {
        // TODO 发送消息
        System.out.println("发给" + userName +" "+msg);
        os.println(msg);
        os.flush();
    }
    
}


本文出自 “阿酷博客源” 博客,请务必保留此出处http://aku28907.blog.51cto.com/5668513/1782187

java利用tcp编程实现简单聊天室

前言:本文是我在学习尚学堂JAVA300集第二季网络编程部分仿照视频内容实现而成具体可以去尚学堂官网观看视频学习一、实现思路  实现聊天室的最核心部分就是JAVA的TCP网络编程。  TCP传输控制协议是一种面向连接的、可... 查看详情

基于tcp的聊天系统

...​该聊天系统的设计采用了Client/Server模型,利用socket网络编程和多线程编程等相关知识开发了一款基于TCP的聊天系统,实现了客户端之间的点对点通信。2、项目运行结果示展示2.1项目开发环境及主要技术​开发环境࿱... 查看详情

基于tcp的聊天系统

...​该聊天系统的设计采用了Client/Server模型,利用socket网络编程和多线程编程等相关知识开发了一款基于TCP的聊天系统,实现了客户端之间的点对点通信。2、项目运行结果示展示2.1项目开发环境及主要技术​开发环境࿱... 查看详情

java网络编程基础--基于tcp/ip的socket编程

...程序支持多客户端的Client/Server服务响应程序在学习JDK的网络编程之前先要了解一下网络基础知识和网络协议。TCP(传输控制协议)一种基于连接的通 查看详情

基于tcp的网络聊天系统(代码片段)

目录一、前言二、产品的介绍1.产品具有的功能2.产品的各个模块 3.使用的开发工具以及应用的技术三、产品的设计1.服务端1.1服务端总流程图1.2数据库及其管理模块设计1.3用户管理模块设计1.4业务模块设计1.5消息的操作1.6消息... 查看详情

基于tcp的聊天系统

...​该聊天系统的设计采用了Client/Server模型,利用socket网络编程和多线程编程等相关知识开发了一款基于TCP的聊天系统,实现了客户端之间的点对点通信。2、项目运行结果示展示2.1项目开发环境及主要技术​开发环境࿱... 查看详情

大数据必学java基础(八十一):基于tcp的网络编程

文章目录​​基于TCP的网络编程​​​​一、功能分解1:单向通信​​​​二、功能分解2:双向通信​​​​三、功能分解3:对象流传送​​​​四、功能分解4:加入完整的处理异常方式​​​​五、功能分解5:多线程接收... 查看详情

基于java的socket简单聊天编程

socket编程:一:什么是socket:socket是BSDUNIX的通信机制,通常称为“套接字”,其英文原意是“孔”或“插座”。有些顾名思义,socket正如其英文原意一样,像是一个多孔插座,可以提供多个端口的连接服务。... 查看详情

java实现一个简单的网络聊天程序

一.TCP通信概述TCP协议是面向连接的通信协议,在传输数据之前,发送端和接收端必须建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服... 查看详情

java案例:基于tcp的简单聊天程序(代码片段)

文章目录一、如何实现TCP通信二、编写C/S架构聊天程序(一)编写服务器端程序-Server.java(二)编写客户端程序-Client.java(三)测试服务器端与客户端能否通信(四)程序优化思路-服务器端采用多... 查看详情

java网络编程基础---基于udp编程

    前面在介绍TCP/IP协议的时候我们已经提到,在TCP/IP协议的传输层除了TCP协议外还有一个UDP协议,相比UDP的应用不如TCP广泛,但是随着计算机网络的发展UDP协议正越来越显示出及其威力,尤其是在需要很强的实时... 查看详情

基于java的简单socket编程

1TCP协议与UDP协议     1.1TCP             TCP是(TranferControlProtocol)的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的... 查看详情

大数据必学java基础(八十一):基于tcp的网络编程(代码片段)

文章目录基于TCP的网络编程一、功能分解1:单向通信二、功能分解2:双向通信三、功能分解3:对象流传送四、功能分解4:加入完整的处理异常方式五、功能分解5:多线程接收用户请求基于TCP的网络编程功能... 查看详情

基于java实现hello/hi简单网络聊天程序

目录Socket简要阐述Socket的概念Socket原理hello/hi的简单网络聊天程序实现服务器端客户端程序执行结果跟踪分析调用栈&LinuxAPI对比创建ServerSocket调用栈图示源码分析Socket绑定调用栈图示源码分析Socket监听调用栈图示源码分析Socket... 查看详情

基于java套接字的简单网络聊天程序

网络中进程之间如何通信本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:消息传递(管道、FIFO、消息队列)同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)共享内存(匿名的和具名的)远程过程... 查看详情

java网络编程基础

...,Java所提供的网络功能可大致分为三类。基于HTTP协议的网络编程:这是三大类功能中最高级的一种。通过URL的网络资源表达方式,很容易确实网络上数据的位置。利用URL和URLConnection,Java程序可以直接读入网络上所放的数据,... 查看详情

网络编程之java简易聊天室实现

最近浅学习了一些关于网络编程方面的知识,视频是跟着狂神学习的,可能学习的不是很深说到网络,相信大家都对TCP、UDP和HTTP协议这些都不是很陌生,学习这部分应该先对端口、Ip地址这些基础知识有一定了解,后面我们都是... 查看详情

基于tcp的聊天系统

目录服务端数据库模块用户管理模块自定义消息类型消息队列服务端核心部分客户端服务端数据库模块数据库模块主要是对数据库的操作,数据的增添,数据的查询要使用C语言连接mysql,需要使用mysql官网提供的库下... 查看详情