package com.network.udp.demo;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import org.junit.Test;
/*
网络编程:主要用于解决计算机与计算机(手机、平板...)之间的数据传输问题;
网络编程:不需要基于html页面就可以达到数据之间的传输;比如:飞秋、QQ、微信。。。
网页编程:就是要基于html页面的基础上进行数据交互的;比如:ao(办公自动化)、高考报考系统。。。
Java方向:
web开发:网络编程几乎用不到;
Android:网络编程很常用;
计算机网络:分布在不同地域的计算机通过外部设备链接起来达到了消息互通、资源共享的效果,就称作为一个计算机网络;
网络通讯的三要素:
1、IP地址:通过IP地址找到目标主机;
2、端口号:通过端口号找到是哪一个应用程序;
3、通讯协议:通过协议规范数据的传输;
IP地址:本质是由一个32位的二进制数据组成的;但是32位数据太难记忆,于是后来为了方便记忆,就把IP地址分成了
4份,每份8位,即2^8 = 0~255,也就是说每位最大为255;
192.168.1.120
00000000-00000000-00000000-00000000
IP地址由两部分组成:网络号 + 主机号;
子网掩码:255.255.255.0;前面三个255表明网络号有三个,主机号有一个;
IP地址分类:
A类地址:一个网络号 + 三个主机号;这就意味着一个A类的IP地址就可以配 2^24 个主机;政府单位用的;
B类地址:两个网络号 + 两个主机号;也就是说一个B类的IP地址可以配 2^16 个主机;事业单位用的(学校、银行...);
C类地址:三个网络号 + 一个主机号;一个C类IP地址可以配 2^8 个主机;私人用的;
IP类:InetAddress;
常用方法:
getLocalHost():获取本地的IP地址对象;
getHostAddress():获取IP地址的字符串表示;
getHostName():获取本地的主机名;
getByName():根据一个主机名获取一个IP地址对象;
端口号:没有类进行描述,因为他仅仅是一个标识符;
端口号范围: 0 ~ 65535
公认端口:0 ~ 1023:系统紧密的绑定了一些服务,不可以使用;
注册端口:1024 ~ 49151:系统松散的绑定了一些服务;有些可以用;
动态或私有端口:49151 ~ 65535:都可以使用;
一般来说,1024 ~ 65535都可以使用,如果遇到不能用的,换一个就行了;
在java中,网络通讯也称为Socket通讯,要求通讯的两台机器必须安装Socket;
网络通讯的协议:
UDP:
1、将数据及其源和目的封装成数据包,不需要建立连接;
2、每个数据包大小不能超过64K;
3、因为无连接,所以不可靠,数据包有可能丢失;
4、因为需要建立连接,所以速度快;
5、UDP通讯是不分服务端与客户端的,只分发送端和接收端;
比如:对讲机,聊天软件,游戏...
UDP协议下的Socket:
DatagramSocket:UDP服务类
DatagramPacket:数据包类
发送端的使用步骤:
1、建立UDP服务
2、准备要发送的数据,并创建数据包,将数据封装到包中
3、调用UDP的服务发送数据包
4、关闭资源;释放占用的端口号;
TCP:
1、面向连接,有特有的通道;
2、连接中可以传输大量数据;
3、通过三次握手连接机制,协议可靠;
4、通信前必须建立连接,效率稍低;
比如:打电话,文件的传输...
*/
public class Demo1Sender {
@Test
public void test1() throws Exception{
// getLocalHost():获取本机的IP地址对象
InetAddress ip = InetAddress.getLocalHost();
System.out.println("IP地址:" + ip.getHostAddress());
System.out.println("主机名:" + ip.getHostName());
// 获取别人机器的IP地址对象
// getByName():根据一个主机名获取一个IP地址对象;
InetAddress inetAddress = InetAddress.getByName("LX-PC");
System.out.println("IP地址:" + inetAddress.getHostAddress());
System.out.println("主机名:" + inetAddress.getHostName());
}
// UDP协议发送端
public static void main(String[] args) throws Exception {
// 1、建立UDP服务
DatagramSocket socket = new DatagramSocket();
// 2、准备要发送的数据,并创建数据包,将数据封装到包中
String data = "UDP发送的数据";
DatagramPacket packet = new DatagramPacket(
data.getBytes(), // 发送数据内容,字节为单位
data.getBytes().length, // 发送数据的字节大小
InetAddress.getLocalHost(), // 发送目的的IP地址对象
9090); // 端口号
// 3、调用UDP的服务发送数据包
socket.send(packet);
// 4、关闭资源;释放占用的端口号;
socket.close();
}
}
package com.network.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/*
* UDP协议接收端
*/
public class Demo1Receive {
public static void main(String[] args) throws IOException {
// 1、创建UDP服务,监听一个端口
DatagramSocket socket = new DatagramSocket(9090);
// 2、创建数据包,准备接受数据
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
// 3、调用UDP服务接收数据;receive()方法是一个阻塞方法,如果没有接收到发送端发送的数据就会一直等待;
socket.receive(packet);
int len = packet.getLength();
System.out.println("接受到的数据:" + new String(buf, 0, len));
// 4、关闭资源
socket.close();
}
}
package com.network.udp.demo;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
使用UDP协议给feiQ发送数据
每个网络程序都有自己所处理的特定格式的数据,如果接收到的数据不符合指定的格式,那么就会被当成垃圾数据丢弃;
制定特定格式的数据就相当于加密;
飞秋接收的数据格式:
version : time : sender : ip : flag : content;
版本号: 时间: 发送人: IP: 发送的标识符: 发送的内容
(聊天的标识符是32)
在UDP协议中,有一个IP地址被称为广播地址,广播地址就是主机号为255地址;
给广播IP地址发送消息的时候,在同一个网络段的机器都可以接收到信息;
*/
public class FeiQDemo {
public static void main(String[] args) throws Exception {
// 建立UDP服务
DatagramSocket socket = new DatagramSocket();
// 准备数据,把数据封装到数据包中
String data = getData("你好飞秋");
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.getBytes().length, InetAddress.getByName("192.168.15.31"), 2425);
// 调用UDP服务发送数据
socket.send(packet);
// 关闭资源
socket.close();
}
// 拼接指定格式的数据
public static String getData(String content){
StringBuilder sb = new StringBuilder();
sb.append("1.0:");
sb.append(System.currentTimeMillis() + ":");
sb.append("战国:");
sb.append("192.168.10.1");
sb.append("32:");
sb.append(content);
return sb.toString();
}
}
UDP群聊测试:
package com.network.udp.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
* 群聊发送端
*/
public class ChatSender extends Thread {
@Override
public void run() {
try{
// 建立UDP服务
DatagramSocket socket = new DatagramSocket();
// 准备数据,把数据封装到数据包中
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line = null;
DatagramPacket packet = null;
while ((line = reader.readLine()) != null){
packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("192.68.69.255"), 9090);
// 发数据发送出去
socket.send(packet);
}
// 关闭资源
socket.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
package com.network.udp.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/*
* 群聊接收端
*/
public class ChatReceive extends Thread {
@Override
public void run() {
try{
// 建立UDP服务,监听一个端口
DatagramSocket socket = new DatagramSocket(9090);
// 准备空的数据包存储数据
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
boolean flag = true;
while (flag){
// 调用UDP服务接收数据
socket.receive(packet);
// 通过数据包获取发送端的IP地址对象
String ip = packet.getAddress().getHostAddress();
System.out.println(ip + "说:" + new String(buf, 0, packet.getLength()));
}
// 关闭资源
socket.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
package com.network.udp.chat;
public class CharMain {
public static void main(String[] args) {
ChatReceive receive = new ChatReceive();
receive.start();
ChatSender sender = new ChatSender();
sender.start();
}
}