Java_网络编程_枚举

1、什么是ip地址
简述:ip地址是网络中计算机的唯一标识。
举例:ipv4–>xx.xx.xx.xx xx是0-255之间的一个数字,4位10进制数
ipv6–>xx.xx.xx.xx.xx.xx -->6位16进制数

局域网ip(通常为192.168.xx.xx),在局域网内,不可以重复
外网ip,在外网环境下不可以重复
【如家中连接的WiFi,移动联通等通信公司给路由器分配一个外网ip,所有连接该wifi的设备被分配一个局域网ip,共用同一个外网ip。】

如何查看本机ip–>ipconfig

每个域名,访问的其实都是某个服务器,服务器其实是一台计算机。
访问域名的时候,其实就是通过服务器的ip地址,找到服务器并获取数据。
域名跟ip地址是一一对应的。【ping 域名 、ping ip地址】

特殊的ip地址,本地ip:
	127.0.0.1 localhost

2,在Java中处理IP地址。
InetAddress表示一个IP地址对象

	//可以根据主机名(计算机名(通过计算机-->属性查看))构建InetAddress对象
	//也可以根据ip地址(字符串)构建InetAddress对象
	InetAddress ia = InetAddress.getByName(String name);
	System.out.println(ia);

3,端口号
我们的电脑上有很多运行的程序,有的程序不需要跟外界交互(单机软件)
有的程序需要跟外界交互,这个时候我们需要通过端口号区分我们要跟那个软件交互。
端口号默认系统分配,也可以有程序向系统申请某一端口号,
同理,局域网ip也由路由器默认分配,但也可向其申请某一局域网ip,
若申请的端口号或ip已被占据,则申请者会遭到拒绝。

总结:通过ip定位计算机,通过port定位哪个软件
注意:端口号是不能重复的。端口号是一个数字(0到6万多)。
百度百科:https://baike.baidu.com/item/%E7%AB%AF%E5%8F%A3%E5%8F%B7/10883658
	可以通过 360流量防火墙-->网络连接 查看各进程端口号		

查看进程端口号的方法
4,通信协议(两个计算机通信遵循的规则)
通信规则:
UDP–>速度快、不需要建立连接、不可靠
TCP—>速度慢、需要通过三次握手建立连接、可靠
举例:UDP:发短信 、、TCP:打电话

网络编程的三要素总结:
IP地址,端口号,通信协议。
5,Socket套接字
在程序中我们通过Socket进行通信,在使用Socket通信的时候
需要指定上面编程的三要素(ip,port,协议)

数据发送分成两步
第一步是监听(等待数据发送过来),用来接收数据。需要指定监听的是哪个端口号
第二步是发送,需要指定发送到哪个计算机(IP地址),需要指定发送到这个计算机的哪个端口号。

Socket中分为发送端和接收端
6,使用UDP发送数据

DatagramSocket ds = new DatagramSocket();//负责发送
	
	//Scanner s = new Scanner(System.in);    //用于循环发送数据
	//while(true){                           //用于循环发送数据
	//String str = s.nextLine();             //用于循环发送数据
	//if(str.equals("end")) break;           //用于循环发送数据
	//创建要发送的信息
	byte[] buf = "udp传送的信息".getBytes();     //用于循环发送数据是数据改为str
	int length = buf.length;
	InetAddress address = InetAddress.getByName("localhost");//指定包裹的目的地地址
	int port = 50000; //一个当前不在运行的端口号
	//int port = 7874;  //指定包裹的目的地端口号
	
	//封装数据的数据包
	DatagramPacket dp = new DatagramPacket(buf,length,address,port);
	
	ds.send(dp);//发送数据
	
	//}                                   //用于循环发送数据
	ds.close();//释放资源

UDP只负责将数据发出去,不管是否有人收到。上述运行成功。
Socket都是要释放资源的,所以常常将socket.close();用finally包裹,以确保资源释放。
(如果不释放资源,socket会一直等待去工作)

7、使用UDP接收数据:

DatagramSocket ds = new DatagramSocket(7874); //指定接收者要监听的本机的某一端口号
	//再次启动该语句,会由于该端口已被绑定(资源未释放)而报异常
	
	byte[] buf = new byte[1024];
	int length = buf.length;
	
	//while(true){                   //用于持续接收数据
	//创建用来装信息的包裹基本组成
	DatagramPacket dp = new DatagramPacket(buf, length);
	
	//使用包裹 dp 去装载接收到的信息,receive后dp中还包含其他关于发送端的信息
	ds.receive(dp);
	
	//将接收到的信息组装成String,length直接返回data的长度
	String s = new String(dp.getData(),0,dp.getLength());
	
	System.out.println(s);
	System.out.println(dp.getAddress());//获取发送端的地址
	
	System.out.println(dp.getPort());//获取发送端的端口号
	//发生端的端口号每次在发送信息时由系统自动分配,所以很有可能每次都不同
	//}                              //用于持续接收数据
	
	ds.close();       //当持续接收数据时,可不释放资源(使其持续等待数据)

启动时先启动接收端,再启动发送端。

8多线程与UDP结合实现双向交流:
根据6,7的内容创建UDP_sendThread和UDP_receiveThread,为聊天1号同时开启发送线程和接收线程,为聊天2号也start发送线程和接收线程,即可双向交流。

9、同理,使用TCP完成持续发送与接收数据:

//使用tcp 发送端(client,客户端)
	//与UDP的不同-->new Socket时会寻找服务器端以求建立连接
	Socket send = new Socket("localhost",7878);//发送到本地7878端口
	
	OutputStream out = send.getOutputStream();
	
	Scanner s = new Scanner(System.in);
	while(true) {
	String str = s.nextLine();
	if(str.equals("end")) break;
	
	out.write(str.getBytes());
	}
	
	send.close();

接收端:

	//接收端(server,服务器端)
	ServerSocket ss = new ServerSocket(7878);//监听7878端口
	
	//程序在这里停止,等待Socket建立连接,发送端new Socket("localhost",7878)时建立连接
	Socket receive = ss.accept();
	
	InputStream is = receive.getInputStream();
	byte[] bt = new byte[1024];
	
	int length =-1;
	
	/*这个输入流要么[管道中有数据-->接收数据],要么处于[管道中没数据-->等待状态],
	   在之前学习的IO流的read方法是不会暂停(等待)的*/
	/*当客户端close-->客户端不再向管道中写数据--->流结束-->输入流的read会返回-1
	与UDP的不同--->服务器端知道客户端的状态*/
	while((length = is.read(bt))!=-1) {
		System.out.println(new String(bt,0,length));
	}
	
	//在得到客户端关闭后,将服务器端进行关闭
	receive.close();
	ss.close();

10、使用TCP实现双向交流
使用【多线程】以及【服务器端Socket与客户端Socket都可获得输入流及输出流】来使服务器端与客户端 都 同时开启接收和进行输入 即可。(注意仍要先打开服务器端,再打开客户端!)
11、使用TCP实现多客户端向服务器端发信息
服务器端持续等待新的客户端的接入,并在每次与客户端接入后在服务器端创建一个新的对应的Socket,使通道连通【该通道建立于一个新的线程,用read来持续等待接收数据】。
12、枚举类型【见名知意,增加代码可读性】

手动实现枚举类型:

class SeasonDemo{
	static final int Spring = 0;
	static final int SUMMER = 1;
	static final int FALL = 2;
	static final int WINTER = 3;
}
-----------------------------------
通过Enum实现枚举类型:

enum SeasonDemo {
//枚举类型,默认数值从0开始+1递增
Spring,SUMMER,FALL,WINTER
}

对枚举类型的应用:

//枚举类型的赋值
SeasonDemo sd1 = SeasonDemo.Spring;
SeasonDemo sd2 = SeasonDemo.WINTER;
	
System.out.println(sd1.name());//返回定义的name:Spring
System.out.println(sd2.ordinal());//返回对应的int值:3
System.out.println(sd1 == SeasonDemo.Spring);//true,Object数据的比较
	
//遍历所有的SeasonDemo值
for(SeasonDemo s:SeasonDemo.values())
	System.out.println(s);
//返回Spring,SUMMER,FALL,WINTER
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章