十一、网络编程

网络编程

网络编程主要用于解决计算机与计算机的数据通信问题。
网络通信三要素:

				  1、ip  
                  2、通信协议 
                  3、端口号:用于表明是给哪一个应用程序来处理。

IP

IP地址:IP地址的本质就是由一个32位的二进制数据组成的。后来为了方便记忆IP地址,就把ip地址切成了4份。每份为8位,每段可以表示2^8(256)个数字,(0-255)

					00000000-00000000-00000000-00000000

IP地址的分类

					IP地址= 网络号 + 主机号

A类地址 =一个网络号+三个主机号 2^24 政府单位
B类地址= 两个网络号+两个主机号 2^16 事业单位
C类地址=三个网络号+一个主机号 2^8 私人使用

我们使用的网络是由运营商注册的一个C类地址,然后在通过路由器分发下来许多ip。

子网掩码的作用就是标识网络号和主机号的位置。 子网掩码中的255对应的就是网络号。
如果IP地址为 192.168.15.31 ,子网掩码为 255.255.255.0 。
那么网络号就为192.168.31 。主机号为31
在这里插入图片描述

InetAddress(IP对象)

InetAddress.getLocalHost()获取本机的IP地址(获取自己的IP地址对象)
InetAddress.getByName(String str) 根据主机名或IP 获取ip地址对象(获取别人的IP地址对象)
InetAddress.getAllByName(“www.baidu.com”) 根据域名获取ip地址【一个域名可能对应多个ip】

ip.getHostName( ) 获取主机名

端口号

端口号范围: 0-65535

0-1023 为公认端口,和系统一些服务进行绑定。
1024–65535 这一范围的端口号,我们可以使用。

通讯协议

网络通信的协议主要有两种协议:

                              1.UDP通信协议
                                           
                                            面向无连接,传输速度快【 面向无连接:把数据封装成数据包直接发送,不需要建立连接(比如对讲机,不管有没有人,都会把消息发送出去)】
                                            每个数据包大小在64K内
                                            因为面向无连接,所以不可靠,容易出现数据丢失问题
                                            udp通信协议不区分客服端与服务端,只区分发送端与接收端
                                            
                                比如:对讲机、飞Q、游戏(如果是面向连接,服务器会等到你连上,才开始游戏,肯定是影响效率,所以游戏基本上是面向无连接的。)            
                               
                                UDP通信协议中有一个IP地址被称作广播地址,广播地址为主机号为255的地址。 如果你的IP为192.168.1.1 。子网掩码为255.255.0.0 ,那么广播地址就是192.168.255.255 【TCP中没有广播地址】

                                          
                              2.TCP通信协议
							                面向连接【通过三次握手机制连接,可靠性协议,但是传输速度慢。】
							                大小不限制

网络通信

在java中网络通信被称为Socket通信,要求通信的两台机器必须要安装Socket。
不同的通信协议就会有不同的Socket。

UDP

UDP通信协议下的Socket:

		DatagrameSocket   udp插座服务
	    DatagramPacket    数据包类

UDP面向无连接,传输过程都会通过数据包进行通信。UDP通信很想码头运输箱的传送过程。运输箱上记载运输的地址。不区分客户端与服务端,只区分发送端与接收端

UDP通信Demo
发送端:

public static void main(String[] args) throws IOException {
		 
		 //建立UDP服务
		 DatagramSocket datagramSocket=new DatagramSocket();
		 
		 //建立数据包
		 String str="大家好";
		 byte[]buf=str.getBytes();
		 DatagramPacket packet=new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 8080);
		 
		 //发送
		 datagramSocket.send(packet);
		 
		 //释放资源--实际上释放占用的端口号
		 datagramSocket.close();
		
		 
	}

接收端:

public static void main(String[] args) throws IOException {
		
		//建立UDP服务,
		DatagramSocket datagramSocket=new DatagramSocket(8080);
		
		while(true) {
			
			//建立数据包
			byte[]buf=new byte[1024];
			DatagramPacket packet=new DatagramPacket(buf, buf.length);
			
			//接受数据存储到数据包
			datagramSocket.receive(packet);
			
			System.out.println(new String(packet.getData()));
		}
	}

自定义UDP发送端与飞秋进行通信
1.飞Q监听2425接口,使用UDP通信协议,此时可以写一个发送端,发送消息给本地2425端口。

public static void main(String[] args) throws IOException {
		 
		 //建立UDP服务
		 DatagramSocket datagramSocket=new DatagramSocket();
		 
		 //建立数据包
		 String str="大家好";
		 byte[]buf=str.getBytes("gbk");
		 DatagramPacket packet=new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 2425);
		 
		 //发送
		 datagramSocket.send(packet);
		 
		 //释放资源--实际上释放占用的端口号
		 datagramSocket.close();
		
		 
	}

2.发送消息,在飞Q中没有接受到。
原因:每个网络程序都有自己所处理的特定格式,如果接受的数据不符合指定的格式,那么就会被当成垃圾数据丢弃。(相当于数据加密)

飞Q接收的数据格式:

		version:time:sender:ip:flag:content
	    版本号    时间   发送人    IP   发送的标志符号(32)   真正的内容

将上述代码改编如下:

	public static void main(String[] args) throws IOException {
		 
		 //建立UDP服务
		 DatagramSocket datagramSocket=new DatagramSocket();
		 
		 //建立数据包
		 String str="大家好";
		 byte[]buf=str.getBytes("gbk");
		 DatagramPacket packet=new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 2425);
		 
		 //发送
		 datagramSocket.send(packet);
		 
		 //释放资源--实际上释放占用的端口号
		 datagramSocket.close();
		
		 
	}
	
	public  static  String  getData(String str) {
		StringBuffer sb=new StringBuffer();
		sb.append("1.0:");
		sb.append(System.currentTimeMillis()+":");
		sb.append("xiao:");
		sb.append("192.168.1.1:");
		sb.append("32:");

		sb.append(str);
		return sb.toString();
		
	}
```c
在这里插入代码片

实现效果:
在这里插入图片描述

udp广播
在UDP通信协议中有一个IP被称为广播IP。 广播IP就是主机号为255的IP。
本地IP : 192.168.0.1
子网掩码:255.255.255.0 ===》》 广播地址:192.168.0.255

本地IP : 192.168.0.1
子网掩码:255.255.0.0 ===》》 广播地址:192.168.255.255

例子:

public static void main(String[] args) throws IOException {
		 
		 //建立UDP服务
		 DatagramSocket datagramSocket=new DatagramSocket();
		 
		 //建立数据包
		 String str=getData("大家好");
		 byte[]buf=str.getBytes("gbk");
		 
		 //广播
		 //本机IP    192.168.0.4
		 //子网掩码  255.255.255.0
		 //广播地址  192.168.0.255
		 DatagramPacket packet=new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.0.255"), 2425);
		 
		 //发送
		 datagramSocket.send(packet);
		 
		 //释放资源--实际上释放占用的端口号
		 datagramSocket.close();
		
		 
	}
	
	public  static  String  getData(String str) {
		StringBuffer sb=new StringBuffer();
		sb.append("1.0:");
		sb.append(System.currentTimeMillis()+":");
		sb.append("xiao:");
		sb.append("192.168.1.1:");
		sb.append("32:");

		sb.append(str);
		return sb.toString();
		
	}
  	

模拟群聊


public class App {
	
	public static void main(String[] args) {
		Sender sender=new Sender();
		sender.start();
		
		Receiver receiver=new Receiver();
		receiver.start();
		
		
	}

}

/**
 * 发送
 * @author Administrator
 *
 */
class Sender extends  Thread{
	 
	@Override
	public void run() {
	   try {
		DatagramSocket sender=new DatagramSocket();
		BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));

		
		while(true) {
			
			String msg = reader.readLine();
			byte[]buf=msg.getBytes();
			DatagramPacket packet=new DatagramPacket(buf, buf.length,InetAddress.getByName("192.168.0.255"),8080);
			
			sender.send(packet);
		}
		
		
		
	} catch (Exception e) {
		
	}
	   
	   
	   
	}
	
}

/**
 * 接受
 * @author Administrator
 *
 */
class Receiver extends Thread {
	
	@Override
	public void run() {
	  try {
		DatagramSocket datagramSocket=new DatagramSocket(8080);
		
		byte[]buf=new byte[1024];
		DatagramPacket packet=new DatagramPacket(buf, buf.length);
		
		while(true) {
			datagramSocket.receive(packet);
			
			System.out.println(packet.getAddress().getHostAddress()+":"+new String(packet.getData()));
		}
		
		
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	  
	
	  
}
}

使用JFrame写一个飞Q

。。。。。。。。。。。。
。。。。。。。。。。。。。
//TODO
//TODO
//TODO
//TODO

TCP

TCP的引入
UDP是一个不可靠的通信协议,数据包可能会丢失。

什么情况下数据会丢失?
1.带宽不足
2.CPU的处理能力不足

在传输exe文件或电影时如果使用udp通信协议,加入丢失一点数据,就会导致整个文件不能使用。所以这时候引入了TCP通信协议。

UDP通信协议特点:
1.面向无连接,传输速度快。
2.UDP是基于数据包进行传输,每个数据包大小限制在64K内
3.因为无连接,所以不可靠。
4.因为不用建立连接,所以速度快。
5.UDP不区分客户端与服务端,只区分发送端与接收端

TCP通信协议的特点:
1.面向连接,传输速度慢,
2.TCP是基于IO流进行数据传输。数据的大小不受限制
3.TCP面向连接,通过三次握手的机制保证数据的完整性(你在么、我在。我收到了。)。可靠协议
4.tcp是面向连接的,所以速度慢。
5.tcp是区分客户端与服务端的

三次握手机制
发送数据前,检测数据通路书否
在这里插入图片描述

为什么ServerSocket不设计一个getInputStream()/getOutPutStream()方法

假如同时有两个用户给服务端发送信息,ServerSocket获取一个输入流,读取信息时,会同时读取到两个信息。 服务器肯定是紊乱。 所以JDK设计了一个Socket类。凡是和服务端建立连接,都会产生一个Socket。
在这里插入图片描述

代码示例
1.使用客户端和服务端实现一问一答。在eclispe中运行客户端。 在cmd中运行服务端。【使用java命令运行字节码文件 java 类的全路径】

客户端

public class Client {
	
	@SuppressWarnings("resource")
	public static void main(String[] args) throws UnknownHostException, IOException {
		
		Socket  socket=new Socket(InetAddress.getLocalHost(),8080);
		
		BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"gbk"));
		BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"gbk"));
		BufferedReader ins=new BufferedReader(new InputStreamReader(System.in));
		
		String content=null;
		while((content=ins.readLine())!=null) {
			writer.write(content+"\r\n");
			writer.flush();
			System.out.println("收到服务端信息:"+reader.readLine());
		}
	
		

	}

}

服务端

public class Server {
	
	public static void main(String[] args) throws IOException {
		
				
		  ServerSocket serverSocket=new ServerSocket(8080);
		  //连接
		  Socket socket = serverSocket.accept();
		  
		  BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"gbk"));
		  BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"gbk"));
		  
		 BufferedReader ins=new BufferedReader(new InputStreamReader(System.in));

		  String content=null;
		  while((content=reader.readLine())!=null) {
			  	System.out.println("收到客户端信息:"+content+"\r\n");
			  
			  	writer.write(ins.readLine()+"\r\n");
				writer.flush();
				
		  }
		  
	}

}


模拟Tomcat
简化版
浏览器本身就是采用了TCP通信原理。
在这里插入图片描述

public class TomcatDemo {
 
	public static void main(String[] args) throws IOException {
		
		ServerSocket serverSocket=new ServerSocket(80);
		
		Socket socket = serverSocket.accept();
		
		BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		
		writer.write("<h1>Hello  World</h1>");
		writer.flush();
		
		
	}
}

在这里插入图片描述

加强版【多线程】

public class TomcatDemo extends Thread {
	
	private Socket socket;
	
	public  TomcatDemo(Socket socket) {
		this.socket=socket;
	}
	
	@Override
	public void run() {


		
		
		try {
			BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

			writer.write("<h1>Hello  World</h1>");
			
			writer.flush();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
 
	public static void main(String[] args) throws IOException {
		ServerSocket serverSocket=new ServerSocket(80);
		while(true) {
			Socket socket = serverSocket.accept();
			new TomcatDemo(socket).start();
		}
		
	}
}

加强版【传输图片】

public class TomcatDemo extends Thread {
	
	private Socket socket;
	
	public  TomcatDemo(Socket socket) {
		this.socket=socket;
	}
	
	@Override
	public void run() {

		try {
			
			FileInputStream in=new FileInputStream(new File("d:/a.jpg"));
			
			OutputStream out = socket.getOutputStream();
			
			int content=-1;
			while((content=in.read())!=-1) {
				out.write(content);
			}
		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
 
	public static void main(String[] args) throws IOException {
		ServerSocket serverSocket=new ServerSocket(80);
		while(true) {
			Socket socket = serverSocket.accept();
			new TomcatDemo(socket).start();
		}
		
	}
}

80是一个特殊的端口,浏览器访问时可以不用写

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值