Java--网络编程

1.网络知识

 网络模型:OSI参考模型,TCP/IP参考模型
 
 IP地址:指网络中设备的标识,网络中每台设备的IP地址不同,各个设备通过IP地址来查找对方实现相互通信
  本地回环地址:127.0.0.1 ;用于网络测试,主机名:localhost
 端口号:
  用于标识进程的逻辑地址,不同进程的标识
  有效端口:0~65535,其中0~1024系统使用或保留端口
  
 传输层主要协议:UDP TCP
  UDP协议特点:
  将数据及源和目的封装成数据包中,不需要建立连接
  每个数据报的大小在限制在64k内
  因无连接,是不可靠协议
  不需要建立连接,速度快
  
  TCP协议特点:
  建立连接,形成传输数据的通道
  在连接中进行大数据量传输
  通过三次握手完成连接,是可靠协议
  必须建立连接,效率会稍低
 
 在java中和网络有关的类都封装在java.net包中,该包中包含了基本的网络编程实现,该包是网络编程的基础。
  InetAddress类:此类表示互联网协议 (IP) 地址,此类无构造函数无法创建
  
  常用方法:
   static InetAddress getByName(String host):在给定主机名的情况下确定主机的 IP 地址
   static InetAddress getLocalHost():返回本地主机
   String getHostAddress():返回 IP 地址字符串(以文本表现形式)
   String getHostName():获取此 IP 地址的主机名
  
  示例:

			import java.net.*;
			public class IpTest{
				public static void main(String[] args) throws Exception{
					//根据主机名确定主机IP地址
					InetAddress ip=InetAddress.getByName("www.itheima.com");
					//以字符串形式获取主机名
					String ipname=ip.getHostName();
					//以字符串形式获取主机ip
					String ipname2=ip.getHostAddress();
					
					System.out.println("ip="+ipname2);
					System.out.println("name="+ipname);
					
				}
			}


 
2.UDP传输
 使用对象:DatagramSocket,DatagramPacket
  DatagramSocket:
  此类表示用来发送和接收数据报包的套接字。
  数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。
  从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
  
  常用方法:
    void receive(DatagramPacket p):从此套接字接收数据报包
    void send(DatagramPacket p):从此套接字发送数据报包
    int getPort():返回此套接字的端口
  
  
  DatagramPacket:
  此类表示数据报包
  数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器
  从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证
  
  常用方法:
   InetAddress getAddress():返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的
   byte[] getData():返回数据缓冲区
   int getLength():返回将要发送或接收到的数据的长度
   int getPort():返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的


  
  操作步骤:
   建立发送端,接收端。
   建立数据包
   调用Socket的发送接收方法
   关闭Socket
  示例:
  

		import java.net.*;
		import java.io.*;
		//发送端
		class UdpSendTest{
			public static void main(String[] args) throws Exception{
				//建立socket(也可指明发送端口)
				DatagramSocket ds=new DatagramSocket(52013);
				//建立数据包,发送端要指明地址,端口
				byte[] buf="hello word".getBytes();
				DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10086);
				//发送数据
				ds.send(dp);
				//关闭资源
				ds.close();
			}
		}
		//接收端
		class UdpReceiverTest{
		public static void main(String[] args) throws Exception{
			//建立DatagramSocket,注意要指明监听的端口
			DatagramSocket ds=new DatagramSocket(10086);
			//建立接收包
			byte[] buf=new byte[1024];
			DatagramPacket dp=new DatagramPacket(buf,buf.length);
			ds.receive(dp);
			//解析数据包
			String text=new String(dp.getData(),0,dp.getLength());
			int port=dp.getPort();
			System.out.println(text+"==="+port);
			//关闭资源,服务端应用程序一般不关闭
			//ds.close();
			}
		}


//练习用UDP协议来创建一个聊天程序,可以在一个窗口中进行信息的发送和接收

示例:

		import java.io.*;
		import java.net.*;
		
		//创建发送信息线程
		class Send implements Runnable{
			private DatagramSocket ds;
			Send(DatagramSocket ds){
				this.ds=ds;
			}
			public void run(){
			try{
			//键盘输入
				BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
				String line=null;
				while((line=bufr.readLine())!=null){
					byte[] buf=line.getBytes();
					//创建发送数据包,将IP地址改为InetAddress.getByName("192.158.155.255")就是群聊程序
					DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),10006);
					//数据包发送
					ds.send(dp);
					if(line.equals("over")){
						ds.close();
						break;
						}
				}
			}catch(Exception e){
				throw new RuntimeException("发送失败");
			}	
		}
		}
		//创建接收信息线程
		class Rece implements Runnable{
			private DatagramSocket ds;
			Rece(DatagramSocket ds){
				this.ds=ds;
			}
			public void run(){
				try{
				//接收端口不断的接收数据
				while(true){
					byte[] buf=new byte[1024];
					//创建接收数据包
					DatagramPacket dp=new DatagramPacket(buf,0,buf.length);
					//接收数据
					ds.receive(dp);
					String text=new String(dp.getData(),0,dp.getLength());
					System.out.println(dp.getAddress().getHostAddress()+" :"+text);
					if(text.equals("over")){
						ds.close();
						break;
						}
					}
				}catch(Exception e){
					throw new RuntimeException("接收端接收失败");
				}
			}
		}
		public class ChatDemo{
			public static void main(String[] args) throws Exception{
				DatagramSocket send=new DatagramSocket();
				DatagramSocket rece=new DatagramSocket(10006);
				new Thread(new Send(send)).start();
				new Thread(new Rece(rece)).start();
			}
		}


  
3.TCP传输
 使用对象:Socket/ServerSocket
  Socket:
  此类实现客户端套接字(也可以就叫“套接字”),套接字是两台机器间通信的端点
  常用构造函数:
   Socket():通过系统默认类型的 SocketImpl 创建未连接套接字
   Socket(InetAddress address, int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口号
  常用方法:
   InetAddress getInetAddress():返回套接字连接的地址(指连接的远程地址,如果未连接则返回null)
   InputStream getInputStream():返回此套接字的输入流
   OutputStream getOutputStream():返回此套接字的输出流
   int getPort():返回此套接字连接到的远程端口
   void close():关闭此套接字
   void shutdownInput():此套接字的输入流置于“流的末尾”。
   void shutdownOutput():禁用此套接字的输出流,也就是表示输出流输了已经结束了

  
  ServerSocket:
  此类实现服务器套接字,服务器套接字等待请求通过网络传入,它基于该请求执行某些操作,然后可能向请求者返回结果
  常用构造函数:
  ServerSocket():创建非绑定服务器套接字
  ServerSocket(int port):创建绑定到特定端口的服务器套接字
  常用方法:
  Socket accept():侦听并接受到此套接字的连接
  void close():关闭此套接字
  InetAddress getInetAddress():返回此服务器套接字的本地地址
  int getLocalPort():返回此套接字在其上侦听的端口

 操作步骤:
  建立客户端和服务器端
  建立连接后,通过Socket中的IO流进行数据的传输
  关闭socket
  
 客户端基本思路:
  客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常
  连接成功,说明客户端与服务端建立了通道,那么 通过IO流就可以进行数据的传输,而Socket对象已经提供了
  输入流和输出流对象,通过 getInputStream(),getOutputStream()获取即可,与服务端通讯结束后,关闭Socket
 服务端基本思路:
  服务端需要明确它要处理的数据是从哪个端口进入的
  当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,
  并通过该对象与客户端通过IO流进行数据传输,当该客户端访问结束,关闭该客户端
  
 示例:

		//向服务端写入数据,服务端收到数据后返回一个信息
		import java.io.*;
		import java.net.*;
		class TcpSocket{
			public static void main(String[] args) throws Exception{
				//建立socket对象,并指明端口号
				Socket s=new Socket("localhost",10086);
				//建立打印流对象,并让其自动刷新
				PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
				//键盘录入
				BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
				//数据输出
				String line=null;
				while((line=bufr.readLine())!=null){
					//数据输入结束标识
					if(line.equals("over"))
						break;
					pw.println(line);
				}
				//输出流结束,如果没有这句标识,服务端无法判断发送端发送的数据什么时候结束,服务端会一直处于
				//阻塞状态,无法向客户端反馈信息,这样会导致客户端也在阻塞状态,这样两端都会处于阻塞状态
				s.shutdownOutput();
				
				bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
				pw=new PrintWriter(System.out,true);
				line=bufr.readLine();
				pw.println(line);
				
				//关闭资源
				bufr.close();
				pw.close();
				s.close();
			}

		}
		class TcpServerSocket{
			public static void main(String[] args) throws Exception{
				//建立服务端对象,并指明监听端口
				ServerSocket ss=new ServerSocket(10086);
				//接收客户端socket对象
				Socket s=ss.accept();
				//建立服务端输入流,其实就是封装客户端的输入流
				BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
				String line=null;
				while((line=bufr.readLine())!=null){
					//打印客户端传入的数据
					System.out.println(line);
				}
				
				PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
				//反馈信息给客户端
				pw.println("hello ,success");
				//s.shutdownOutput();
				//关闭资源,服务端一般不关闭,但这只是个小程序,只对客户端服务一次,可以关闭
				ss.close();
				bufr.close();
				pw.close();
			}
			
		}



 //练习,客户端向服务端上传一张图片,上传成功后服务端返回上传成功信息
  示例:

		import java.net.*;
		import java.io.*;
		//客户端
		class TcpClient{
			public static void main(String[] args) throws Exception{
				//建立socket对象
				Socket s=new Socket("localhost",10086);
				//建立输入输出流对象,因为是字节流,所以缓冲流应该是字节缓冲流
				BufferedInputStream bin=new BufferedInputStream(new FileInputStream("1.bmp"));
				BufferedOutputStream bout=new BufferedOutputStream(s.getOutputStream());
				//将数据进行上传
				byte[] buf=new byte[1024];
				int len=0;
				while((len=bin.read(buf))!=-1){
					bout.write(buf,0,len);
					bout.flush();
				}
				//输出流结束标识
				s.shutdownOutput();
				
				//接收服务端发送过来的信息
				bin=new BufferedInputStream(s.getInputStream());
				while((len=bin.read(buf))!=-1){
					String message=new String(buf,0,len);
					System.out.println(message);
				}
				//关闭资源
				s.close();
				bin.close();
				bout.close();
			}
		}

		//发送端
		class TcpServer{
			public static void main(String[] args) throws Exception{
				//建立serversocket,指明监听端口
				ServerSocket ss=new ServerSocket(10086);
				//监听客户端,接收客户端
				Socket s=ss.accept();
				//建立输入输出流
				BufferedInputStream bin=new BufferedInputStream(s.getInputStream());
				BufferedOutputStream bout=new BufferedOutputStream(new FileOutputStream("load.bmp"));
				//接收图片
				byte[] buf=new byte[1024];
				int len=0;
				while((len=bin.read(buf))!=-1){
					bout.write(buf,0,len);
					bout.flush();
				}
				
				//向客户端反馈信息
				bout=new BufferedOutputStream(s.getOutputStream());
				String message="你好,上传成功!";
				bout.write(message.getBytes(),0,message.getBytes().length);
				//要刷新
				bout.flush();
				s.shutdownOutput();
				
				//关闭资源
				bin.close();
				bout.close();
				ss.close();
				
			}

		}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值