【JAVA课设】-- Socket实现实时通信

这篇具有很好参考价值的文章主要介绍了【JAVA课设】-- Socket实现实时通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近学期末了,Java要求做一个课程设计,需要用Java网络编程、JDBC、SWT进行设计。研究了 很久之后终于在各路大佬的指引下成功完工。

根据在计网学习的知识,通信大致分为两种,用Socket,ServerSocket类实现的TCP服务,和用DatagramSocket类实现的UDP通信服务。

详细代码使用可以参考这位大佬的文章。Java 网络编程_ZaynFox的博客-CSDN博客_java网络编程

一、TCP 与Socket ServerSocket

首先来说一下如何使用Socket,ServerSocket类实现的TCP服务。实现原理如下面这位大佬的图。

Socket实现即时通讯服务(一)_一只菜鸟.....的博客-CSDN博客_socket实时通信

【JAVA课设】-- Socket实现实时通信

 从这里我们可以很清晰的看出来分为两个步骤。

第一步是监听,也就是accept()之前的内容

第二步是收发数据。是在建立连接之后的内容。

1.1 Socket 类建立通信的原理

首先我们来讲第一步——监听,Socket类是如何建立通信的。

Socket的通信方式类似于传统的C/S模式,首先Client客户端要创建一个Socket类的对象,通过构造函数Socket(String 发送IP,int 发送进程占用的端口号)生成一个Socket对象。

然后客户机创建一个ServerSocket类的对象,通过构造函数ServerSocket(int 接收占用的端口号)。并且使用serverSocket.accept()方法进入“接听阻塞”状态。

Socket在使用构造函数创建对象的同时,会占用发送端口和ServerSocket尝试进行TCP连接。如果创建Socket时使用的端口,恰好有ServerSocket在监听,就可以建立连接。

建立连接的方式是,通过serverSocket.accept()返回一个Socket对象。

//Client 端
Socket socket = new Socket("127.0.0.1",1314);

//Server 端
ServerSocket serverSocket = new ServerSocket(1314);//与上面的端口要一致。
Socket socket2 = serverSocket.accept();

到此连接部分就成功了,接下来我们就进入了第二步。如何通过serverSocket.accept()返回的Socket对象进行消息的接收发送。

1.2 Socket 收发消息— —输入输出流

1.2.1 输出数据 — — socket.getOutputStream()

//输出数据 拿过话筒

/*
 * 连接好的socket获取输出流获取的是一个话筒, 返回值是OutputStream 
 * 但是DataOutputStream用的更多,所以类型转化一下
 */
OutputStream outToServer = null;
System.out.println("接收输出流,此时" + socket);
outToServer = socket.getOutputStream();

DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF(message); // 向流中写入数据
out.flush(); // 清空流

看过一个形象的说法,通过socket.getOutputStream()输出数据就像拿过了话筒一样。

socket.getOutputStream()返回的是一个OutputStream类型的输出流,通过实例化一个对象 outToServer接收Socket通信中的输出流,就可以得到“发言权”。就是直接在outToServer里面写数据就可以实现通信发数据的功能了。

非常的简单和神奇,这个流就好像C中指针一样,指向通信中的通信信道。

1.2.2 读入数据 — — socket.getInputStream()

String receiveMsg = "";
InputStream inFromServer = socket.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
receiveMsg = in.readUTF(); // 从输入流中读取数据

和接收数据一样,通过socket.getInputStream()可以得到一个输入流,通过输入流的读取函数我们就可以读出其中的字符,实现接收信息的功能。

二、线程类Thread 实现实时通信

看到这里你肯定觉得实现实时通信,至少是实现通信是一件非常简单的事情了。下面给你一串代码,我们来一起试试会有什么样的问题。

//Client 端
public class Client{


}
//Server 端
public class Server{



}
//主函数

public class TCPCommunication{

public void main(){
}
}

可以看出来,这个只能实现一对一的C/S通信(也就是只能一个人一直说话,另一个人只能听不能说)。并且还不能断开连接,毕竟我们确实没有设置让while(true)停止的语句。

此时比较聪明的读者就发下了,只要在同一台电脑上同时运行两种代码不就好了吗?他就可以实现发送和接收两种功能了。

上面的想法很好也是我一开始的想法,因此我们再放一段代码我们来一次看看。问题远不止于此。

可以看出来有 xxx 问题。

接下来我们加入我们的主角Thread类。

这样就解决了连接不能多次监听的问题。但是这样依然没有解决 ServerSocket.accept()阻塞的进程 以及 GetInputStraem带来的阻塞问题。

我们可以通过调用线程池来解决,通过最终解决了问题。

最终代码如下

github 链接:

gitee 链接:

百度云链接:

package NetCommunication;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import DATABASE.database;

public class Net {
    public Socket socket = null; // 全局的socket变量 用于表示当前对象所建立的唯一的连接
    ServerSocket serverSocket;
    /*
     * 流程就是首先打开页面的时候就创建一个ServerSocket 尝试接收
     * 返回一个Socket后就成功建立连接了 接收成功就断开ServerSocket连接
     */

    // 连接相关的各种标志
    public boolean LinkSuccessFlag = false;// 没连接成功的时候就是0

    // 端口和IP参数
    public int ReceivePort = 12101; // 所有主机的接收端口和发送端口用一样的。
    public int SendPort = 12101;

    // 存入数据库的相关信息
    public String myUserName;
    public String toUserName;

    // 设置一个set函数
    public void setmyUserName(String myUserName) {
        this.myUserName = myUserName;
    }

    public void settoUserName(String toUserName) {
        this.toUserName = toUserName;
    }


    // 创建一个发送方 发送只需要一个单独的函数方法不需要线程类
    public int createClient(String SendIP) {
        // 主动连接他人。连接成功时候将成功连接的Flag赋值为1
        // 参数都用外界传入
        if (LinkSuccessFlag == false) {// 还没连接成功
            System.out.println("还没被被动连接,现在开始主动连接" + SendIP);
            try {
                socket = new Socket(SendIP, SendPort);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
            LinkSuccessFlag = true;
            System.out.println("主动连接成功");
            // 创建成功返回1
            return 1;
        } else {

            System.out.println("已经被动连接成功了,不需要主动连接了");
            System.out.println("被动连接到:" + socket);
            return 1;
        }


    }

    // 创建一个接收方 监听需要放在线程里面,因为会线程阻塞。
    Thread TServer = new Server();

    public class Server extends Thread {
        public void run() {
            createServer();
        }
    }

    public void startServer() {
        TServer.start();
    }

    public void createServer() {
        if (LinkSuccessFlag == false) {// 还没连接成功 但是本项目使用过程中其实就直接在每个窗口打开的时候就进行连接了。
            if (serverSocket != null) {
                System.out.println("已经开始监听了,不需要在创建一个");
            } else {
                System.out.println("还没连接,现在开始被动监听,等待别人主动连接。监听端口是" + ReceivePort);
                try {
                    serverSocket = new ServerSocket(ReceivePort);
                    serverSocket.setSoTimeout(0);//
                    System.out.println("开始accept监听");
                    socket = serverSocket.accept();
                    System.out.println("被连上了" + socket);
                    LinkSuccessFlag = true;
                } catch (IOException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }

            }
        } else {
            System.out.println("已经连接成功了,不需要被动监听了");
            System.out.println("已经被动连接到了 socket:" + socket);
        }

    }

    // 关闭接收方
    public void endServer() {
        try {
            if (serverSocket != null) {
                serverSocket.close(); // 关闭监听

                System.out.println("进入endServer了,关闭的效果" + serverSocket);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*--------------------收发信息阶段 已经获取连接用的socket了-----------------------------------*/
    /*
     * 实现思路是通过连接的输入输出流进行通信。 断开通信的方式是使用标签不在允许通信
     */

    // 收发相关的标签
    public boolean AllowSRFlag = true;//允许收和发送信息

    public void sendString(String message) {
        if (AllowSRFlag == true) {

            try {
                /*
                 * 连接好的socket获取输出流获取的是一个话筒, 返回值是OutputStream
                 * 但是DataOutputStream用的更多,所以类型转化一下
                 */
                OutputStream outToServer = null;
                System.out.println("接收输出流,此时" + socket);
                outToServer = socket.getOutputStream();

                DataOutputStream out = new DataOutputStream(outToServer);
                out.writeUTF(message); // 向流中写入数据
                out.flush(); // 清空流

            } catch (IOException ioException) {
                ioException.printStackTrace();

            }
        } else {
            System.out.println("收发已经不被允许了,已经点过断开连接按钮辽");
        }
    }

    /* 终止函数 */
    public void endSendandReceive() {
        AllowSRFlag = false;
        TReceiveStr.interrupt();
    }

    // 接收需要用线程,因为有监听和接收socket的原因一样
    Thread TReceiveStr = new ReceiveString();

    public class ReceiveString extends Thread {
        public void run() {
            receiveString();
        }
    }

    /* 调用函数 */
    public void startReceiveString() {
        TReceiveStr.start();
    }

    public void receiveString() {
        /* 接收线程里面开一个定时任务 循环接收 */
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {

                System.out.println("调用到接收监听函数");
                if (AllowSRFlag == true) {
                    String receiveMsg = "没接收到";
                    try {
                        InputStream inFromServer = socket.getInputStream();
                        DataInputStream in = new DataInputStream(inFromServer);
                        receiveMsg = in.readUTF(); // 从输入流中读取数据
                        System.out.println("接收到对方发来" + receiveMsg);
                        /* 聊天记录插入数据库 */
                        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss ");
                        Date date = new Date(System.currentTimeMillis());

                        String time = formatter.format(date);

                        System.out.println("输入数据库的内容为" + myUserName + toUserName + time + receiveMsg);
                        database insert = new database();
                        insert.InsertTalkRecord(myUserName, toUserName, time, receiveMsg);

                        // result = ""; //结果清空 便于下一次取新的数据
                    } catch (IOException e) {
                        receiveMsg = "接收出现异常,没接收到";
                        e.printStackTrace();
                    }
                } else {
                    return;
                }
            }

        };
        // 在指定延迟0毫秒后开始,随后地执行以2000毫秒间隔执行timerTask
        new Timer().schedule(timerTask, 0L, 2000L);
        // return receiveMsg;

    }
}

看完此文不知道你有没有一点收获呢?如果有的话,希望可以收获你一个免费的点赞~~。你的点赞和支持是我创作的最大动力。

 文章来源地址https://www.toymoban.com/news/detail-404735.html

到了这里,关于【JAVA课设】-- Socket实现实时通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot(java)实现websocket实现实时通信

    WebSockets是一种在Web应用程序中实现实时通信的技术。它允许客户端和服务器之间建立持久的、双向的通信通道,从而使得服务器可以实时向客户端推送数据,而不需要客户端不断地向服务器发起请求。这种实时通信的能力对于需要即时更新数据的应用程序非常有用,比如在线

    2024年04月29日
    浏览(53)
  • Java实现socket通信详解(UDP/TCP)c/s模式

    在实现具体代码前,我们先来简单了解下TCP/UDP协议 TCP在OSI模型中位于传输层在网络层之上,故在端到端传输的基础上将数据以端口号等标识实现进程/终端设备应用的区分, 将数据精准的传达。 TCP全称为传输控制协议具有以下特点: 面向有连接的服务可靠的数据传输,即在

    2023年04月08日
    浏览(37)
  • websocket实时通讯和socket.io实时通信库的使用;心跳机制与断线重连

    https://zh.javascript.info/websocket WebSocket 是一种网络通信协议,就类似于 HTTP 也是一种通信协议。 为什么需要 WebSocket? 因为 HTTP 协议有一个缺陷:通信只能由客户端发起。 代码解析: 创建WebSocket实例:通过 new WebSocket() 创建一个WebSocket实例。在括号中传入服务器的URL,该URL指定了

    2024年02月16日
    浏览(42)
  • 用java套接字socket实现两台电脑间的通信

    实现效果: 一方发送简单的文字消息 发送、接收复杂的图片、音频、文档等 相互之间实现自由通信 java对网络编程的支持 前提条件:两台电脑在一个局域网内,比如连接了同一个路由器 将一台电脑作为服务端,一台作为客户端 实现中遇到的问题: ip地址连接不上 发送的消

    2023年04月17日
    浏览(47)
  • 网络编程-Socket通信实现服务器与客户端互传文件(JAVA语言实现)

    在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换. 网络编程三要素:ip地址、端口、协议 ip地址: 每台计算机指定的一个标识符,127.0.0.1是回送地址,可以代表本机地址 ,一般用来测试使用 ipconfig:命令行中查看本机地址 ping ip地址:检查网络是

    2023年04月14日
    浏览(47)
  • 【Java网络编程】基于UDP-Socket 实现客户端、服务器通信

    ​ 哈喽,大家好~我是你们的老朋友: 保护小周ღ   本期为大家带来的是网络编程的 UDP Socket 套接字,基于 UDP协议的 Socket 实现客户端服务器通信 ,Socket 套接字可以理解为是,传输层给应用层提供的一组 API,如此程序,确定不来看看嘛~~ 本期收录于博主的专栏 : JavaEE_保

    2024年02月02日
    浏览(71)
  • 了解JS三种实时通信方式——Eventsource、websocket与socket.io之间的差异和优缺点

    EventSource EventSource 是一种轻量级的 API,用于获取来自服务器的实时事件。它是 WebSockets 的替代方案,因为它比 WebSockets 更简单,更适合处理服务器向客户端发送数据的情况。使用 EventSource ,只有服务器能够发送消息,所以它更安全。但是,它不支持双向通信或客户端发送消

    2024年02月08日
    浏览(49)
  • 【Java】网络编程与Socket套接字、UDP编程和TCP编程实现客户端和服务端通信

    为什么需要网络编程? 现在网络普及程序越来越高,网络上保存着我们日常生活中需要的各种资源,使用程序通过网络来获取这些资源的过程就需要网络编程来实现。 什么是网络编程? 网络编程,指网络上的主机,通过不同的进程以程序的方式实现网络通信(网络数据传输)

    2024年02月17日
    浏览(79)
  • Java【网络编程2】使用 TCP 的 Socket API 实现客户端服务器通信(保姆级教学, 附代码)

    📕各位读者好, 我是小陈, 这是我的个人主页 📗小陈还在持续努力学习编程, 努力通过博客输出所学知识 📘如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽 📙 希望我的专栏能够帮助到你: JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统

    2024年02月05日
    浏览(65)
  • 用python的socket通信将Yolov5的USB摄像头实时推理结果发送给另一台电脑

    将配置yolov5的电脑当客户端,局域网内的另一台电脑当服务端,利用python的socket通讯,将客户端Yolov5的USB摄像头实时推理结果发送给另一台电脑的服务端。 一、修改Yolov5的detect.py文件,启动客户端 1.1在文件前添加 import socket #include 1.2在 LOGGER.info前添加以下代码 # Print time (

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包