开发思路:
服务端两个Socket:
  1. UDP的DatagramSocket接收客户端消息。
  2. 广播multicastSocket 发送广播消息

客户端一个Socket:

  1. multicastSocket 接收服务端发来的广播 (不允许客户端直接发广播),同时发送点对点数据到UDP服务端DatagramSocket 。
  2. javax.swing.* 提供客户端图形化界面

生疏知识点:

图形化界面按钮监控键盘

addActionListener(AbstractAction接口实现类);监听器。
topTextField.getInputMap().put(KeyStroke.getKeyStroke('\n'),"confirm_username"); 键盘事件和名字关联;
topTextField.getActionMap().put("confirm_username",confirmListener); 事件别名和监听器关联
服务器端程序:
package tcpandudp.udpexample;

import java.io.IOException;
import java.net.*; /**
* @ClassName MulticastServerScoket
* @projectName: object1
* @author: Zhangmingda
* @description: 设计思想:为避免所有人直接发广播,导致消息内容无环节把控,消息发送的时候,发送到非广播端口(作为一个服务端)再由此服务端向广播地址发送消息,
* date: 2021/5/13.
*/
public class MulticastServerScoket {
/**
* 广播Socket端口
*/
private static final int BROAD_PORT = 30000;
/**
* 广播IP地址 :224.0.0.0 到 239.255.255.255
*/
private static final String BROAD_IP = "230.3.3.3";
/**
* 服务端口
*/
private static final int SERVER_PORT = 8888;
private void start(){
try (
/**
* 广播用套接字
*/
MulticastSocket multicastSocket = new MulticastSocket(BROAD_PORT);
/**
* 服务端套接字
*/
DatagramSocket datagramSocket = new DatagramSocket(SERVER_PORT)
){
/**
* 广播IP地址
*/
InetAddress multi_addr = InetAddress.getByName(BROAD_IP);
/**
* 广播套接字配置接收广播的IP地址
*/
multicastSocket.joinGroup(multi_addr);
/**
* 构建接收UDP数据的包
*/
byte[] inBuff = new byte[4096];
DatagramPacket inPacket = new DatagramPacket(inBuff,inBuff.length);
/**
* 接收广播,并广播出去
*/
while (true){
//普通套接字收广播
datagramSocket.receive(inPacket); String content = new String(inPacket.getData(),0,inPacket.getLength());
System.out.println(content);
//广播套接字发广播
DatagramPacket outPacket = new DatagramPacket(inPacket.getData(),inPacket.getLength(),multi_addr,BROAD_PORT);
multicastSocket.send(outPacket);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 程序入口
*/
public static void main(String[] args) {
new MulticastServerScoket().start();
}
}

客户端

package tcpandudp.udpexample;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicReference; /**
* @ClassName MulticastClientSocket
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/5/13.
*/
public class MulticastClientSocket {
/**
* 广播Socket端口
*/
private static final int BROAD_PORT = 30000;
/**
* 广播IP地址 :224.0.0.0 到 239.255.255.255
*/
private static final String BROAD_IP = "230.3.3.3"; /**
* 要发送数据包的服务端IP地址和 端口
*/
private static final String SERVER_IP = "127.0.0.1";
private static final int SERVER_PORT = 8888; private void go() {
JFrame jFrame = new JFrame("广播聊天客户端");
//上部
JPanel topPanel = new JPanel();
JTextField topTextField = new JTextField(30);
JButton topButton = new JButton("确认用户名");
topPanel.add(topTextField);
topPanel.add(topButton);
jFrame.add(topPanel, BorderLayout.NORTH);
//中部
JTextArea centerArea = new JTextArea(10,40);
JScrollPane centerPane = new JScrollPane(centerArea);
jFrame.add(centerPane);
//下
JPanel bottomPanel = new JPanel();
JTextField bottomTextField = new JTextField(35);
JButton sendButton = new JButton("发送");
bottomPanel.add(bottomTextField);
bottomPanel.add(sendButton);
jFrame.add(bottomPanel, BorderLayout.SOUTH); jFrame.setLocation(400,300);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.pack();
jFrame.setVisible(true);
AtomicReference<String> username = new AtomicReference<>("");
//确认用户名事件监听器
Action confirmListener = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
String topTextContent = topTextField.getText();
if (topTextContent != null && ! "".equals(topTextContent)){
username.set(topTextContent);
System.out.println("用户名设置成功");
}
}
};
//绑定事件监听器
topButton.addActionListener(confirmListener);
topTextField.getInputMap().put(KeyStroke.getKeyStroke('\n'),"confirm_username");
topTextField.getActionMap().put("confirm_username",confirmListener);
/**
* 发送&接收用socket
*/
try{
MulticastSocket mClinetSocket = new MulticastSocket(BROAD_PORT);
InetAddress multi_addr = InetAddress.getByName(BROAD_IP);
/**
* 接收端
*/
new Thread(){
@Override
public void run() {
byte[] inBuff = new byte[4096];
/**
* 构建接收包
*/
DatagramPacket inPacket = new DatagramPacket(inBuff,0,inBuff.length);
while (true){
/**
* 接收数据放包里,转为字符串打印出来
*/
try {
mClinetSocket.receive(inPacket);
} catch (IOException e) {
e.printStackTrace();
}
String content = new String(inPacket.getData(),0, inPacket.getLength());
System.out.println(content);
centerArea.append(content + "\n"); //向文本框加入文本
}
}
}.start();
/**
* 套接字加入广播地址
*/
mClinetSocket.joinGroup(multi_addr); /**
* 服务端地址构建
*/
InetAddress server_addr = InetAddress.getByName(SERVER_IP);
/**
* 构建发出包
*/
DatagramPacket outPacket = new DatagramPacket(new byte[0],0,server_addr,SERVER_PORT);
/**
* 发送按钮监听器
*/
Action sendListener = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
if (username.get().equals("")){
System.err.println("请输入用户名");
}else {
String sendContent = bottomTextField.getText();
if (sendContent != null && ! "".equals(sendContent)){
sendContent = username + ":" + sendContent;
//输入字节存入包,
outPacket.setData(sendContent.getBytes());
try {
mClinetSocket.send(outPacket);
bottomTextField.setText(null);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
};
/**
* 发送按钮绑定监听器
*/
sendButton.addActionListener(sendListener);
//内容框监听键盘
bottomTextField.getInputMap().put(KeyStroke.getKeyStroke('\n'),"send");
bottomTextField.getActionMap().put("send",sendListener);
} catch (IOException e) {
e.printStackTrace();
} } public static void main(String[] args) {
new MulticastClientSocket().go();
}
}

java 网络编程基础 UDP协议DatagramSocket,MulticastSocket 实现局域网聊天软件(Server + Client模式)的更多相关文章

  1. java 网络编程基础 UDP协议的Socket:DatagramSocket;广播Socket:MulticastSocket

    什么是UDP协议: UDP协议是一种不可靠的网络协议,它在通信实例的两端各建立一个Socket 但这两个 Socket之间并没有虚拟链路,这两个Socket只是发送.接收数据报的对象.Java 提供了 ...

  2. java:网络编程(UDP (DatagramSocket和DatagramPacket)正则表达式)

    java:网络编程(UDP (DatagramSocket和DatagramPacket)正则表达式) * TCP* 特点:面向连接,点对点的通信,效率较低,但安全可靠* UDP:用户数据报协议,类似 ...

  3. Java网络编程和NIO详解开篇:Java网络编程基础

    Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...

  4. Java网络编程基础(Netty预备知识)

    今天在家休息,闲来无事,写篇博客,陶冶下情操~~~ =================我是分割线================ 最近在重新学习Java网络编程基础,以便后续进行Netty的学习. 整 ...

  5. java网络编程基础——TCP网络编程一

    基于TCP协议的网络编程 TCP/IP协议是一种可靠的网络协议,它的通信的两端各自建立一个Socket,从而在通信的两端之间形成网络虚拟链路. Java使用Socket对象来代表两端的通信端口,并通过 ...

  6. java网络编程基础——网络基础

    java网络编程 网络编程基础 1.常用的网络拓扑结构: 星型网络.总线网络.环线网络.树形网络.星型环线网络 2.通信协议的组成 通信协议通常由3部分组成: 语义部分:用于决定通信双方对话类型 语法 ...

  7. JAVA基础知识之网络编程——-基于UDP协议的通信例子

    UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...

  8. Java学习笔记52(网络编程:UDP协议案例)

    InetAddress类: 表示互联网中的IP地址,示例: package demo; import java.net.InetAddress; import java.net.UnknownHost ...

  9. java 网络编程基础 TCP/IP协议:服务端ServerSocket;客户端Socket; 采用多线程方式处理网络请求

    1.Java中客户端和服务器端通信的简单实例 Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一 ...

随机推荐

  1. [CSP-S2019] 树的重心

    也是一个很不错的题目. 考虑我们钦定重心为根. 那么就有这样一个性质: 如果我们断的边在一个点的子树里,则这个点不会成为断边后的分裂树的根. 所以我们就只要考虑断边在子树外即可. 那么我们设\(x\) ...

  2. Codeforces 407E - k-d-sequence(单调栈+扫描线+线段树)

    Codeforces 题面传送门 & 洛谷题面传送门 深感自己线段树学得不扎实-- 首先特判掉 \(d=0\) 的情况,显然这种情况下满足条件的区间 \([l,r]\) 中的数必须相同,双针扫 ...

  3. P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)

    题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...

  4. CF932F Escape Through Leaf

    CF932F Escape Through Leaf 首先, $ O(n^2) $ dp 是很显然的,方程长这样: \[dp[u] = min\{dp[v] + a_u\times b_v\} \] ...

  5. DirectX12 3D 游戏开发与实战第五章内容

    渲染流水线 学习目标: 了解用于在2D图像中表现出场景立体感和空间深度感等真实效果的关键因素 探索如何用Direct3D表示3D对象 学习如何建立虚拟摄像机 理解渲染流水线,根据给定的3D场景的几何描 ...

  6. nginx_access_log的格式设置

    log_format <NAME> <Strin­­­g>; 关键字 格式标签 日志格式 关键字:其中关键字error_log不能改变 格式标签:格式标签是给一套日志格式设置一 ...

  7. kubernetes部署haproxy、keepalived为kube-apiserver做集群

    也可以用nginx.keepalived做负载均衡,看大家的需求. # yum -y install haproxy keepalived haproxy的配置文件(三台一样): cat > / ...

  8. 基于python win32setpixel api 实现计算机图形学相关操作

    最近读研期间上了计算机可视化的课,老师也对计算机图形学的实现布置了相关的作业.虽然我没有系统地学过图形可视化的课,但是我之前逆向过一些游戏引擎,除了保护驱动之外,因为要做透视,接触过一些计算机图形学的 ...

  9. Mybatis相关知识点(二)

    Mybatis解决jdbc编程的问题 1. 数据库连接创建.释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题. 解决:在SqlMapConfig.xml中配置数据连接池,使用 ...

  10. canal从mysql拉取数据,并以protobuf的格式往kafka中写数据

    大致思路: canal去mysql拉取数据,放在canal所在的节点上,并且自身对外提供一个tcp服务,我们只要写一个连接该服务的客户端,去拉取数据并且指定往kafka写数据的格式就能达到以proto ...