(28)后续需要整理的内容...

介绍UDP通信协议的编程之前,先介绍一下网络编程,socket相关的概念:

网络编程:网络编程主要用于解决计算机与计算机(手机平板等)之间的数据传输问题。

网络编程:不需要基于html网页就可以达到数据之间的传输。比如,飞秋,QQ,微信等等

网页编程:基于html页面的基础上进行数据的交互与传输。比如说淘宝,oa(办公自动化)等

计算机网络:分布在不同地域的计算机通过外部设备相互连接起来达到了消息互通,资源共享的效果,这就叫做计算机网络、

网络通讯的三要素:

1、IP,计算机在网络中唯一的身份标识

2、端口号:用于表明该消息是给那个应用程序处理的,只不过是一个标识符而已。

3、协议:一种规范,保障硬件间的良好兼容

IP地址:ip地址的本质就是一个有32位的二进制数组成的数据。

00000000-00000000-00000000-00000000  为了便于记忆,每8bit(1Byte)转换成一个十进制的数,0-255

IP地址是 由网络号+主机号 组成的。子网掩码位数,就是网络号的位数

IP地址的分类

A类地址:1个网络号 + 3个主机号  2^24 政府单位使用

B类地址:2个网络号 + 2个主机号  2^16 事业单位使用

C类地址:3个网络号 + 1个主机号  2^ 8 私人使用

Java中的IP类:InetAddress

常用的方法:

getLocalHost() 获取本机的ip地址 对象. ——静态方法

getByName("IP或者主机名")根据主机名或者一个ip地址的字符串形式,生成一个一片地址《对象》(获取别人的主机地址)

getHostAddress() 返回一个本机的ip地址字符串的形式

getHostName() 返回计算机的主机名

InetAddress.getAllByName("ip地址、主机名、域名") 返回一个InetAddress[]

InetAddress[] arr =  InetAddress.getAllByName("www.baidu.com");

for (InetAddress inetAddress : arr)

{

System.out.println(inetAddress.getHostAddress());

}

上面的getAllByName("www.baidu.com")你可以发现输出的是两台主机,并不是一台主机有两个ip地址的问题。www.baidu.com是一个域名,这个域名需要有ISR供应商的dns服务器进行解析,一般百度之类的大公司,在ISR那注册的服务器都不知一个,白的就是上面两个,这两个服务器的作用主要就是为了实现转发的功能在这两个服务器的后面可能还有大批的服务器集群。

端口号:是没有用来描述的,端口号只相当于一个标识而已。

端口号的范围0-65535之间。

端口号不是对标指定的,有一下的分类:其中后两类基本上都能使用

公认端口(WellKnownPorts):从0到1023,它们紧密绑定(binding)于一些服务。

注册端口(RegisteredPorts):从1024到49151。它们松散地绑定于一些服务。

动态和/或私有端口(Dynamicand/orPrivatePorts):从49152到65535。

常用端口:

21    FTP

80    HTTP

443  HTTPS

网络通信的协议:

UDP通信协议

TCP通信协议

在Java中网络通讯也称之为Socket(套接字,插座)通信,要求通信的两端都要安装Socket。

不同的协议就有不同的插座(Socket)

UDP通信协议

的特点

1、将数据极其源和目的封装为数据包,面向无连接。

2、每个数据包大小限制在64K中

3、因为无连接,所以不可靠,有可能出现数据包丢失的情况

4、因为不需要建立连接,所以速度快

5、udp通信部分服务端与客户端,只分发送端与接收端

如:人说话、对讲机、飞秋、凌波、CS枪战游戏等

udp协议下的Socket:

DatagramSocket(udp插座服务):发送与接收都是用该类

DatagramPacket(数据包类)

DatagramPacket(buf, length, address, port)

buf发送的内容

length发送内容的大小

address发送的目的地ip地址对象

port是一个端口号

发送端的使用步骤:

1、建立udp的服务

2、准备数据,把数据封装到数据包中发送

3、发送端的数据包要带上一个ip地址与端口号。

3、调用udp的服务发送数据。

4、关闭资源

 1 //发送端 完全模拟码头发货的过程
 2 public class Demo1Sender
 3 {
 4     public static void main(String[] args) throws IOException
 5     {
 6         //建立udp的服务
 7         DatagramSocket datagramSocket = new DatagramSocket();//直接使用午餐构造方法就行了
 8         //准备数据,把数据封装到发送包中
 9         String data = "这是一个udp的例子...";
10         DatagramPacket datagramPacket = new DatagramPacket(data.getBytes(), data.getBytes().length, InetAddress.getLocalHost(), 9090);
11         //调用udp的服务发送数据包
12         datagramSocket.send(datagramPacket);
13         //关闭资源---实际上就是释放占用的端口号
14         datagramSocket.close();
15     }
16 }

接收端的使用步骤

1、建立udp的服务。

2、准备空的数据包,接受数据。(只要制定一个字节数组)

3、调用udp的服务接受数据。

4、关闭资源。

 1 //接收端
 2 public class Demo1Recieve
 3 {
 4     public static void main(String[] args) throws IOException
 5     {
 6         //建立udp插座服务,监听一个端口
 7         DatagramSocket datagramSocket = new DatagramSocket(9090);
 8         //准备空的数据包用于存储数据
 9         byte[] buf = new byte[1024];
10         DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
11         //调用udp的服务接受数据
12         datagramSocket.receive(datagramPacket);    //数据实际上存储到了 buf 字节数组中.recieve方法是一个阻塞方法,没有接收到数据就会一直处于阻塞状态。
13
14         System.out.println("接收端接受到的数据:"+new String(buf, 0, datagramPacket.getLength()));//getLength()获取数据包存储的字节,到底接受了多少字节,datagramPacket最清楚
15
16         //关闭资源
17         datagramSocket.close();
18     }
19 }

很明显运行上面的示例程序的时候,应当先启动接收端的,接收端处于一种等待接收信息的阻塞状态。然后在运行发送端的,发送端运行,发出数据,接收端接受数据之后,程序接受。

群聊示例,关键是接收端发送端一定要使用多线程,发送端的消息数据包中的地址应

 1 当是广播地址。
 2 发送端:
 3 public class ChatSender extends Thread
 4 {
 5     @Override
 6     public void run()
 7     {
 8         //建立udp的服务
 9         try
10         {
11             DatagramSocket socket = new DatagramSocket();    //发送端不需要地址
12             //准备数据,把数据封装到数据包中
13             BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));
14             String line = null;
15             DatagramPacket packet = null;
16             while((line = keyReader.readLine())!=null)
17             {
18                 //把数据封装到数据包中,发送出去
19                 packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("192.168.1.255"), 9090);
20                 //把数据包发送出去
21                 socket.send(packet);
22             }
23             //关闭资源
24             socket.close();
25         } catch (SocketException e)
26         {
27             // TODO Auto-generated catch block
28             e.printStackTrace();
29         } catch (UnknownHostException e)
30         {
31             // TODO Auto-generated catch block
32             e.printStackTrace();
33         } catch (IOException e)
34         {
35             // TODO Auto-generated catch block
36             e.printStackTrace();
37         }
38     }
39 }
40 接收端:
41 //群聊的接收端
42 public class ChatRecieve extends Thread
43 {
44     @Override
45     public void run()
46     {
47         try
48         {
49             //建立udp的服务,接收端要监听一个端口
50             DatagramSocket socket = new DatagramSocket(9090);
51             //准备一个空的集装箱
52             byte[] buf = new byte[1024];
53             DatagramPacket packet = new DatagramPacket(buf, buf.length);
54             boolean flag = true;
55             while(flag)
56             {
57                 socket.receive(packet);
58                 //packet.getAddress()获取发送数据包的IP地址对象
59                 System.out.println(packet.getAddress().getHostAddress()+"说:"+new String(buf, 0, packet.getLength()));
60             }
61             //关闭资源
62             socket.close();
63         } catch (SocketException e)
64         {
65             // TODO Auto-generated catch block
66             e.printStackTrace();
67         } catch (IOException e)
68         {
69             // TODO Auto-generated catch block
70             e.printStackTrace();
71         }
72     }
73 }
74 //主程序
75 public class ChatMain
76 {
77     public static void main(String[] args)
78     {
79         ChatRecieve chatRecieve = new ChatRecieve();
80         chatRecieve.start();
81
82         ChatSender chatSender = new ChatSender();
83         chatSender.start();
84     }
85 }
86 启动主程序即可。
时间: 2024-12-16 06:05:05

(28)后续需要整理的内容...的相关文章

jquery 性能优化的28个建议[整理]

一.选择器性能优化建议  1.总是从#id选择器来继承这是jquery选择器的一条黄金法则.jquery选择一个元素最快的方法就是用ID来选择. $('#content').hide(); 或者从ID选择器继承来选择多个元素: $('#content p').hide(); 2. 在class前面使用tag jQuery中第二快的选择器就是tag选择器(如$(‘head’)),因为它和直接来自于原生的Javascript方 法getElementByTagName().所以最好总是用tag来修饰

【linux命令总结】——后续用到的内容持续补充和更新

比如说:某个文件是go文件,名字叫做 Hello.go 1.通过后台运行某个程序,将结果输出到某个文件, 如果是直接运行go程序:go run Hello.go 后台运行:nohup go run Hello.go & ,然后就会将结果输出到nohup.out中 2.查看实时更新的日志信息 查看某个文件的内容,比如非实时的这种,并且不做修改:cat Hello.go 查看实时的信息:tail -f nohup.out    (备注:这里的文件是nohup.out的文件) 3.查找端口号并且杀进程

最近公共祖先-------4.28(没整理完)

最近公共祖先:在一个有根树中,结点u.v的最近公共祖先是满足是u,v的公共祖先并且深度尽可能大的结点. 1.倍增法 首先如果两个点的深度如果不同,将深度较大的点跳到与深度较小的点一样的深度,再同时向上跳,首次相遇时即为最近公共祖先. #include<bits/stdc++.h> using namespace std; const int maxn=10000+15; vector<int>vec[maxn];//记录树的边 int n,m,x,y,p,q,t; int dad[

Linux运维(十)-2016-12-9整理

也有段时间没有整理面试题目了,这几天呢,完成了2场实习生和1场校招,十分郁闷,为什么金融运维一点都不关注技术,在乎我的学校成绩,我尼玛想说,学校那么水的课程能说明什么,跟技术有一丁丁点关系吗?我学业成绩不好,就能否定我的专业岗位基础不行吗?唉,劳资想说,你如果质疑我的能力,你就问我,劳资要是被你虐倒是我算我输,学艺不精我就服,看过去有球用. 这辈子职业生涯都不想进外包和IDC这两种类型的公司,就是TM打杂的,薪资还低,关键是不厚道,比如垃圾胜蓝.这回校招那家是我之前就提到的那家,大多数人对我是认

HTML 用JS增加table一行所有内容的实现

  因为对JS用的不多,最近需要写界面的时候需要实现——通过点击一个button让table增加一行(和前面行内的内容一致,无论是dropdown还是checkbox).可自己硬是无从下手,从网上搜的答案总是各有不同.最后自己通过这样的方法实现了: 步骤基本是这样的: 在script里面写一个Function如下. 最后就简单了,我们直接通过<input type="button" value="More" name="More" clas

整理对Spark SQL的理解

Catalyst Catalyst是与Spark解耦的一个独立库,是一个impl-free的执行计划的生成和优化框架. 目前与Spark Core还是耦合的,对此user邮件组里有人对此提出疑问,见mail. 以下是Catalyst较早时候的架构图,展示的是代码结构和处理流程. Catalyst定位 其他系统如果想基于Spark做一些类sql.标准sql甚至其他查询语言的查询,需要基于Catalyst提供的解析器.执行计划树结构.逻辑执行计划的处理规则体系等类体系来实现执行计划的解析.生成.优化

修改MySQL 5.7.9版本的root密码方法以及一些新变化整理

MySQL 5.7版本开始,增强密码验证机制,网上说安装的时候会在/root/.mysql_secret  文件中生成默认密码,这一点自 5.7.6版本以后也去掉了. 针对如果生成默认密码,网上有一个版本,内容如下: 1.修改配置文件,一般在 /etc/my.cnf, 在[mysqld]字段下增加skip-grant-tables 字段,用以忽略权限验证: 2.重启MySQL服务器,CentOS 7.0操作命令是: 1 systemctl restart mysqld.service 3.使用m

28._动态内存分配

动态内存分配 传统数组的缺点(静态内存分配):   1.数组长度必须事先指定,且只能是常整数,不能是变量    例子:     int a[5]; //OK     int len = 5; int a[len]; //error   2.传统形式定义的数组,该数组的内存程序员无法手动编    程释放,在一个函数运行期间,系统为该函数中数组所     分配的空间会一直存在,直到该函数运行完毕时,数组    元素所占存储空间才会被系统释放 3.数组的长度一旦定义,长度就能被改变     4.A函数

Java通过jni技术支持c、c++调用使用整理

最近在公司搞终端5.0,说要对c++版本sdk封装一个java版的sdk,可是团队没有搞java的,于是赶鸭子上架,临时学习几天,整了一下:感觉还挺有意思的,于是整理一下: 为什么要使用java支持对c.c++的调用? 众所周知Java语言是一门支持跨平台解释型语言:#.java通过javac编译生成生成#.class字节码,运行过程依赖java虚拟机执行字节码生成虚拟机的执行指令,最终通过虚拟机操控所在平台,完成其设计的功能:其优点很明显,支持跨平台:其缺点也很明显,执行效率底,并且不支持平台