JAVA 网络编程 - 实现 群聊 程序

Posted cyjiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA 网络编程 - 实现 群聊 程序相关的知识,希望对你有一定的参考价值。

在实现 这个 程序之前, 我们 需要 了解 一些 关于 Java 网络 编程 的 知识.

 基本 的 网络知识:

网络模型

OSI (Open System Interconnection 开放系统互连) 参考模型.

TCP/IP 参考模型.


网络通讯要素

IP 地址

端口号

传输协议




*** 网络编程 指的就是 网络技术 和 IO 技术的综合.

 


网络参考模型.

OSI 参考模型 TCP/IP

应用层---------------------

表示层 应用层

会话层---------------------

传输层 传输层

网络层 网际层

数据链路层-----------------
主机 至 网络层
物理层--------------------


网络 7 层





*** ipconfig/all 物理地址. . . . . . . . . . . . . : 54-3H-4L-7P-44-JK , 这个地址 是全球 唯一的. (这个 是 网卡的标识号)


IP 地址: InetAddress

网络中 设备的标识. 例如: 192.168.1.23 (这个网段 通常用于 局域网) 最大 为 255

不易记忆, 可用主机名(更易于记忆) 例如: 我的 主机名 FDSJLAKJFL 和 IP 地址对应, 也是 唯一的.


每一台计算机中 都有网卡(MAC)地址, 这个地址 默认 绑定的 一个 IP 地址, 默认就是 127.0.0.1 (如果 访问的 主机是自己的 话, 就可以用 这个 地址来访问.)
本地 回环地址: 127.0.0.1 主机名: localhost

端口

用于标识 进程的 逻辑地址, 不同进程的标识.

有效端口: 0!65535, 其中 0 ~ 1024 是 系统使用 或 保留端口.

*** 传输协议

通讯的规则

常见协议: TCP, UDP



// *** 检测 网卡是否正常工作.

 

C:Users>ping 127.0.0.1

正在 Ping 127.0.0.1 具有 32 字节的数据:
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128
来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128

127.0.0.1 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 0ms,最长 = 0ms,平均 = 0ms


如果 不是以上结果, 而是 失败了话, 就很有可能 是 网卡 出了问题.

 

// *** 可用于 访问 的网站 有很多 游戏广告, 可以将 这些 游戏广告的 域名 写到 hosts 文件中来. 就打不开 哪些 广告 网站, 只会 打开自己 设置的 hosts 文件 中的 IP 地址 所对应的 .
*** 配置 hosts 文件. 127.0.0.1 www.game.com.cn

本机中 没有此资源, 表示 该页面 无法显示.

 

序列号, 将 校验的 网站的 IP 地址 改为 自己 电脑的 IP 地址, 自己电脑中 是没有 这个 校验 程序的, 所以 就 哦了. 软件 每次 联网 校验 都没用, 所以就可以免费使用了.

不过 首先要知道 校验的网站的 域名是什么.(360 地址列表)

 

端口

*** 在计算机中, 就 0 ~ 65535 六万 多个 端口 是可以用的, 而 0 ~ 1024 这些端口 尽量不要用, 这些 端口 很多 都 对应着 Windows 系统中的 应用程序,
*** 你要用了 , Windows 就用不了了. 数字标识 得 具有唯一性, 不能 两个 程序 用一个 端口.

 

 关于 TCP, UDP, Socket, IO 流的 了解 和 使用:

TCP/UDP


UDP (数据报文包协议)

将 数据及 源 和 目的 封装成 数据包中, 不需要建立连接. 面向 无连接.

每个 数据包的 大小 限制在 64k 内.

因 无连接, 是 不可靠协议 不管对方在不在, (没 连接上 也行), 打个包(64k 内), 放个地址,就送.

不需要建立连接, 速度快. : 好处



TCP (传输控制协议)

建立连接, 形成传输数据的通道. 保证对方在,(建立连接)

在连接中 进行大数据量 传输.

通过 三次 握手 完成 连接, 是 可靠协议. 你在吗? 我在. 我知道了. 三次握手.

必须建立 连接, 效率 会 稍低.

 

例如: TCP 就 相当于 打电话. UDP 就相当于 对讲机.

 

 

Socket

Socket 就是为 网络服务提供的一种 机制.

通信的 两端都有 Socket.

网络通信 其实就是 Socket 间的通信.

数据在 两个 Socket 间通过 IO 传输.

 


TCP 用的 是 客户端 和 服务端 进行通讯的.


UDP 分的是 发送 和 接收.

TCP 分的是 客户端 和 服务端.

 

 

关于 局域网 中的 广播地址:

  

        255 广播 地址, 我发一句, 到 广播地址, 广播 地址 发给 这个 网段中 所有的 主机, 你看到,我也会看到, 就实现了 聊天 功能,只要我们在 同一个 局域网中.就哦了.

  

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPChatTest {

	
	public static void main(String[] args)  throws IOException{
		
		/*
		 * 
		 * 案例一:  通过 UDP 实现 群聊程序.
		 * 
		 * 思路:
		 * 
		 * 	这个程序中 既有 收 又有 发 , 那么 需要同时 执行, 需要使用 多线程 技术.
		 * 
		 * 	一个线程 负责发, 一个 线程 负责收, 需要两个任务.(线程任务);
		 * 
		 * */
		
	// 发送端 的Socket , 接收端 的 Socket;
		
		DatagramSocket sendSocket = new DatagramSocket();
		DatagramSocket receSocket = new DatagramSocket(10000);
	
		// 创建 任务 对象.
		
		Send send = new Send(sendSocket);
		
		Rece rece = new Rece(receSocket);
		
		
		// *** 创建 线程 并开启.
		
		Thread t1 = new Thread(send); // *** 发
		
		Thread t2 = new Thread(rece); // *** 收
		
		t1.start();
		
		t2.start();
		
	}
}


/*
 * 
 * 
 * 	255 广播 地址, 我发一句, 到 广播地址, 广播 地址 发给 这个 网段中 所有的 主机, 你看到,我也会看到, 就实现了 聊天 功能,只要我们在 同一个 局域网中.就哦了.
 * 
 * 
 * */
// 发送任务                      这里 先把 架子 搭起来 , 都需要 哪些 东西.

class Send implements Runnable{
	
	private DatagramSocket ds;
	
	public Send(DatagramSocket ds) {
		
		this.ds = ds;
		
	}
	
	@Override
	public void run() {
		
	//	System.out.println("UDP2 发送端 run ");
		
		// *** 这里写的端口号 如果 已经 有 程序在使用了, 就不能用 这个 端口号了, 程序会启动不起来, 因为 端口号 冲突了.(会 发生 地址 已被  占用 异常.)
		// *** 数据来自于 键盘录入.
		
		
		try {
			

			BufferedReader bufin = new BufferedReader(new InputStreamReader(System.in)); // *** 键盘 录入 也是 阻塞式的, 你没录入 就不会 停止, 一直 阻塞在 这里.
			String line = null;
			while((line = bufin.readLine()) != null) {
				
				
				
				
				byte[] buf= line.getBytes(); // *** 将数据 转成 数组.
				
				DatagramPacket dp = new DatagramPacket( buf,buf.length,InetAddress.getByName("192.168.1.255"),10000);
				// *** 这里的 地址 可以写成 其他人的  IP 地址 和 端口号 ,就可以 进行 聊天了.
				ds.send(dp);
				
				// *** 既然是 键盘 录入, 那么 就一定要 加一个 结束 标记.
				
				if("886".equals(line)) {
					
					break;
					
				}	
				
				
			}
			
			// *** 关闭 资源
			ds.close();
		} catch (IOException e) {
		
		}
		
		
		
	}
		
}
	


// 接收任务.
class Rece implements Runnable{

	
	private DatagramSocket ds;
	
	public Rece(DatagramSocket ds) {
		
		this.ds = ds;
	}
	@Override
	public void run() {
	//	System.out.println("udp2 接收端 run ");
		
		while(true) {
		
			
			try {
				
				byte[] buf = new byte[1024];
				
				DatagramPacket dp = new DatagramPacket(buf, buf.length);
				
				
					ds.receive(dp); // *** 阻塞, 如果 没有接收到 数据 就会 一直阻塞在这里.
			
				
				String ip = dp.getAddress().getHostAddress();
				
				int port = dp.getPort();
				
				String text = new String(dp.getData(),0,dp.getLength());
				
				System.out.println(ip + ":" + port+ ":" + text);
				
				if(text.equals("886")) {
					
					System.out.println(ip + "...离开 聊天室" );
					
				}
			 }catch(IOException e) {			 
			 }
		
			// ds.close();  *** 一直在 接收, 收 别人 发过来的 数据, 我就不用 关闭 资源了.
		
		
		}
		
	}
		
}

  

  这个 程序 使用的 环境 是 在一个 局域网中,   只要 启动 这个 程序, 发的 消息 会通过 255 这个 广播 地址 发送到 在这个 网段内的 主机中,  那么 大家 就都可以 看见, 就可以 实现 聊天 功能,  当然 ,

  IP 地址 也可以使用 你自己的 主机 IP 地址, 只是 你自己 的 IP 地址 是不具备 广播的 功能的, 别人 还是 可以 发送给 你信息, 你肯定 可以 看到, 但是 别人 那里 只是 显示 发出了 消息, 不会 显示 回复的 消息, 因为 我写的程序 发送的 IP 地址 不是 给他的.  

 

感谢 毕

 

 

以上是关于JAVA 网络编程 - 实现 群聊 程序的主要内容,如果未能解决你的问题,请参考以下文章

java socket编程实现群聊(超详细)

第97题JAVA高级技术-网络编程16(简易聊天室11:实现客户端群聊)

第97题JAVA高级技术-网络编程16(简易聊天室11:实现客户端群聊)

Java编程实例-tcp聊天室代码实现

java 网络编程之UDP通信和简单的群聊程序

Java 网络编程:案例四:多个客户端群聊