黑马程序员 网络编程

------- android培训java培训、期待与您交流! ----------


网络编程



Java中的.net包提供了网络通信的类和服务。

1.网络模型:OSI参考模型和TCP/IP参考模型。

一般来说开发处于传输层和网际层。应用层为:FTP和HTTP协议等。传输层为:UDP和TCP等。网际层为:IP。
通常用户操作的是应用层,而编程人员需要做的是传输层和网际层,用户在应用层操作的数据,经过逐层封包,最后到物理层发送到另一个模型中,再进行逐层解包,最后回到应用层


2.网络通信的要素

  • 找到对方IP
  • 数据要发送到指定的应用网络上,为了标识这些程序,故给这些网络应用程序都使用数字进行标识。为了方便称呼其为端口,逻辑端口
  • 定义通信规则。这个通信规则被称为协议,国际网络通信通用协议TCP/IP。


IP地址在Java中对应的对象是InetAddress。它有几个重要的方法:
  • static InetAddress getByName(String host):获取指定主机的IP和主机名。这个方法是静态的,注意到这个类不能直接new对象,只能通过其本身的静态方法得到 本类对象。
  • String getHostAddress():返回IP地址字符串文本形式。
  • String getHostName():返回IP地址主机名。
  • public static InetAddress getLocalHost():返回本地主机。


一个获取指定主机的例子


import java.net.*;
class getIP
{
	public static void main(String[] args)throws Exception 
	{
		//获取本机的Address对象
		InetAddress ia=InetAddress.getLocalHost();
		
		//打印本机的名字及地址
		String name=ia.getHostName();
		String address=ia.getHostAddress();
		System.out.println(name+" "+address);


		//获取指定主机的ip信息
		InetAddress i=InetAddress.getByName("127.0.0.1");
		String na=i.getHostName();
		String add=i.getHostAddress();
		System.out.println(name+" "+address);
		//当获取的主机返回的对象不唯一时可以使用InetAddress.getAllByName方法,返回的是一个InetAddress数组


	}
}



3.TCP与UDP

UDP:

  • 不需要建立连接,将数据和源封装在数据包中。
  • 每个数据包的大小限制在64k以内,数据超过64k将自动拆分。
  • 面向无连接,所以是不可靠协议。
  • 因为不需要连接,所以速度快



TCP:

  • 需要建立连接,形成数据传输的通道。
  • 可以在数据连接中进行大数据量的传输。
  • 通过三次握手完成连接,是可靠的协议。
  • 必须建立连接,效率稍低。

三次握手:第一次本方发送请求,第二次对方确认连接,第三次本方再次确认连接成功。


无论是UDP还是TCP连接,其使用的基类都是Socket类。


4.Socket



Socket是实现两台主机网络通信的端点,使用Socket类及其方法可以轻松完成网络通信的任务。
Socket的常用构造方法:
  • public Socket(InetAddress address,int port):创建一个Socket对象并将其连接到指定 IP 地址的指定端口号。
  • public Socket(String host,int port):也可以直接给出指定IP和端口来创建Socket对象。


Socket常用方法:
  • public InetAddress getInetAddress():返回包含该Socket对象连接主机的InetAddress对象。
  • public InputStream getInputStream():返回该Socket对象的输入流,一般用于TCP传输。
  • public OutputStream getOutputStream():返回该Socket对象的输出流,一般用于TCP传输。
  • public boolean isConnected():测试是否连接成功,连接成功则返回true。




5.UDP通信



Socket有一个可实现子类DatagramSocket用于给UDP通信。
DatagramSocket常用方法:
  • public void connect(InetAddress address,int port):连接到指定地址和端口。当连接到远程地址时,包就只能从该地址发送或接收。
  • public boolean isConnected():返回连接状态,若已连接则返回true。
  • public void send(DatagramPacket p):发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。 
  • public void receive(DatagramPacket p):接收数据报包。返回的信息会覆盖掉原DatagramPacket的内容。
  • DatagramPacket数据报包,这个包包含了将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
DatagramPacket构造方法有:
  • public DatagramPacket(byte[] buf,int length):构造 DatagramPacket,用来接收长度为 length 的数据包。 
  • DatagramPacket(byte[] buf, int length, InetAddress address, int port) :构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
DatagramPacket常用方法有:
  • public InetAddress getAddress():返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
  • public int getPort():返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。 
  • public byte[] getData():返回数据缓冲区。
  • public int getLength():返回将要发送或接收到的数据的长度。
  • public void setAddress(InetAddress iaddr):设置要将此数据报发往的那台机器的 IP 地址。
  • public void setPort(int iport):设置要将此数据报发往的远程主机上的端口号。 
  • public void setData(byte[] buf):为此包设置数据缓冲区。




使用Udp进行通信时:
  1. 建立两个DatagramSocket,接收端的Socket必须制定一个端口。
  2. 建立数据包,将数据和接收端的地址和端口都封装进去
  3. 调用发送端Socket的send方法,将数据包发送出去
  4. 接收端,通过receive方法接收数据包
  5. 关闭资源 


发送端:
class ChatSend
{
	private DatagramSocket ds;
	
	ChatSend()
	{
		try 
		{
			ds = new DatagramSocket();
		} 
		catch (SocketException e) 
		{
			System.out.println("未建立连接服务");
			return;
		}
	}
	public void chat()
	{
		
		try 
		{
			byte[] buf = "这是一个小程序".getBytes();
			ds.send(new DatagramPacket(buf,buf.length,
					 InetAddress.getByName("127.0.0.1"),10010));
			//将要发送的数据转成数组后打包成DatagramPacket并发送出去
			ds.close();
			
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}	
		
	}
	
}



接收端:


class ChatReceive
{
	private DatagramSocket ds;
	
	ChatReceive()
	{
		try 
		{
			ds = new DatagramSocket(10000);
		} 
		catch (SocketException e) 
		{
			System.out.println("未建立连接服务");
			return;
		}
	}
	public void chat()
	{
		try 
		{
			byte[] by = new byte[1024*64];
			DatagramPacket dp = new DatagramPacket(by,by.length);
			//新建一个空包用来存放数据
			ds.receive(dp);
			//结束数据并存放在空包内
			String ip = dp.getAddress().getHostAddress();
			int port  = dp.getPort();
			String data = new String(dp.getData(),0,dp.getLength());
			System.out.println(ip+":"+port+" "+data);
			//获取包内信息
			ds.close();
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}	
		
	}
	
}




6.TCP通信


TCP通信要用到专门的服务端ServerSocket。这个类主要用来接收Socket对象。
ServerSocket构造方法有:
  • public ServerSocket(int port):创建绑定到特定端口的SeverSocket对象。
ServerSocket常用方法有:
  • public Socket accept():从监听端口接收发送过来的Socket对象。
  • public int getLocalPort():返回监听的端口地址。


使用TCP通信的一般步骤:

服务端:

  1. 建立服务端的Socket服务,并监听一个端口;(SeverSocket)
  2.   获取连接过来的客户端对象,通过SeverSocket的accept方法。该方法为阻塞式方法;
  3.   .客户端如果发送数据,那么服务端就要使用对应的对象,并且使用客户端的对象的读取流来获得数据
  4.   关闭客户端。
  5.    .关闭服务端(可选)。





class ChatRece
{
	private ServerSocket ss= null;
	ChatRece()
	{
		try 
		{
			ss = new ServerSocket(10086);
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	public void chat()
	{
		
		while(true)
		{	
			try 
			{
				Socket s = ss.accept();
				new Thread(new ChatServerThread(s)).start();	
				//每接受一个服务端就新建一个通信。
			} 
			catch (IOException e)
			{
				System.out.println("建立连接失败");
				continue;
			}	
		}	
	}
}


class ChatServerThread implements Runnable
{
	private Socket s;
	ChatServerThread(Socket s)
	{
		this.s = s;
		InetAddress ia = s.getInetAddress();
		String address = ia.getHostAddress();
		System.out.println(address+"已建立连接");//获得客户端的ip信息
	}
	public void run()
	{
		try
		{
			//读取数据,经过获得的Socket对象的读取流读出数据
			BufferedReader bfr = new BufferedReader(new InputStreamReader(s.getInputStream()));
		
			String data = null;
			while((data = bfr.readLine())!=null)
			{
				System.out.println(data);
			}
		}
		catch (IOException e) 
		{
			e.printStackTrace();
		}
	}
}




客户端

  1. 建立客户端的Socket服务,指定主机和一个端口;
  2. 为了发送数据要获得Socket中的输入输出流。
  3. 使用客户端的write方法就可以向服务端发送数据了
  4. 关闭客户端。


class ChatSe
{
	private Socket s= null;
	private InetAddress ia =null;
	ChatSe(String adress,int port)
	{
		try 
		{
			ia = InetAddress.getByName(adress);
			s = new Socket(ia,port);//建立指定端口的Socket服务
			System.out.println("建立连接成功");
		} 
		catch (Exception e)
		{
			System.out.println("建立连接失败"); 
			return;
		}	
	}
	public void chat()
	{
		try
		{
			BufferedWriter bfw = new BufferedWriter(
						new OutputStreamWriter(s.getOutputStream()));
			BufferedReader bfr = new BufferedReader(
						new InputStreamReader(System.in)); 
			//信息从键盘输入并传给服务端
			String data = null;
			while((data = bfr.readLine())!=null)
			{
				if(data.equals("over"))//设定信息结束标记
					break;
				bfw.write(data);
				bfw.newLine();//必要的,由于readline是不读取/r/n的如果不加这句,
						//在服务端就读取不到/r/n,读取就不能结束
				bfw.flush();
			}
			s.shutdownOutput();//关闭客户端的输出流。相当于给流中加入一个结束标记-1. 


			bfr.close();
			s.close();
		}
		catch(IOException e)
		{
			System.out.println("发送数据失败");
		}
		
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值