黑马程序员——Java网络编程

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

常用的网络模型有两种:OSI参考模型和TCP/IP参考模型,OSI模型分七层分别为应用层、表示层、会话层、传输层、网络层、数据链路层和物理层,对应于TCP/IP模型的应用层、传输层、网络层和物理链路层。Java中的网络传输是基于套接字机制,要进行网络通信必须要指定通信三要素:IP地址、端口号以及遵循的传输协议类型。

一、网络通信三要素:

1、Java中使用InetAddress类对IP地址进行了封装,该对象提供了许多方便调用的静态方法,如getByName()、getAllByName(),getByAddress()、getLocalHost()等静态方法,获取对应主机的IP地址,返回类型为InetAddress或InetAddress[],同时该对象还提供了其他一些有用的非静态方法如getAddress(),getHostAddress()、getHostName()等能够很方便的获取相关信息。

2、端口号:它是用于标识网络应用程序进程的一种逻辑标识,通过它可以知道网络通信的对方是那个应用程序进程。

3、传输协议类型——常用的两个传输协议UDP和TCP,及用户数据报协议和传输控制协议。两者特点总结如下:

UDP:面向无连接的、不可靠的传输协议,而且对传输的数据报大小进行限制,最大不能超过64K,并且传输过程中不能保证数据一定能够到 达收信者,但其传输效率较高,通常用于一些实时性较强的网络通信中,比如实时聊天、视频等。

TCP:面向连接的、可靠的传输协议,保证传输过程中数据报一定到达收信者,而且连接过程要经历三次握手,对数据包的传输大小没有限制 ,可以进行大数据量的传输,但由于传输过程保证了数据的可靠性,使得其传输效率不如udp高,通常用于传输数据的应用程序。

二、网络编程——socket

socket是为了网络服务而提供的一种机制,通信的收发双方都有socket,网络通信实际上就是通信双方之间的socket的通信过程,数据在socket间是通过IO传输的。

1、UDP传输方式:两个重要的类——DatagramSocket用于发送和接收数据的套接字,DatagramPacket用于udp发送和接收数据时对数据包的封装。

udp传输方式进行网络编程的步骤:发送端——创建套接字对象,系统会为其随机分配一个端口号或者可以指定自己的端口号,然后,定义一个数据包,用于填装发送的数据,将发送数据写入数据报,定义一个DatagramPacket对象,将数据大包,并在其构造函数中指明发送端的IP和端口信息。最后,调用套接字的send方法,将数据发送到指定地点。

接收端:首先,定义一个套接字,并制定自己的端口号信息,用作标识发送端数据的目的地;然后,定义一个数据包用作接收数据,创建DatagramPacket对象,并调用套接字的receive方法,将发送来的数据打包给接收端的数据包。

import java.net.*;
import java.io.*;

/*
需求:在发送端通过键盘录入,将数据传输到接收端显示
该程序会对异常进行处理,而是直接抛出。
*/
class UdpChatSend
{
	public static void main(String[] args) throws Exception
	{
		//创建套接字对象
		DatagramSocket ds=new DatagramSocket();
		//通过键盘录入进行信息交互
		BufferedReader bufR=new BufferedReader(new InputStreamReader(System.in));
		//byte[] buf=new byte[1024];
		String line=null;
		while((line=bufR.readLine())!=null)
		{
			if("over".equals(line))
				break;
			//定义一个发送数据包
			byte[] buf=line.getBytes();
			//将发送数据打包给一个DatagramPacket对象,通过该对象指定发送目的端
			DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.158"),5001);
			//调用send发送将数据发往接收端即可,不保证发送的数据一定接收
			ds.send(dp);
			System.out.println("192.168.1.158"+"::"+line);
		}
		bufR.close();
		ds.close();
	}
}
class UdpChatRecv
{
	public static void main(String[] args) throws Exception
	{
		//创建接收端的套接字对象,并指定其端口号,标识接收方的进程
		DatagramSocket ds=new DatagramSocket(5001);
		byte[] buf=new byte[1024];
		while(true)
		{
			
			DatagramPacket dp=new DatagramPacket(buf,buf.length);
			//接收发送来的数据,
			ds.receive(dp);
			//通过DatagramPacket对象,获取发送来的数据
			String ip=dp.getAddress().getHostAddress();
			String str=new String(dp.getData(),0,dp.getLength());
			System.out.println(ip+"::"+str);
		}
		//ds.close();
	}
}

2、TCP传输方式:要分客户端和服务端,在客户端用Socket套接字,服务端则使用ServerSocket套接字进行通信,通过调用套接字的getInputStream()和getOutputStream()方法来获取套接字的输入流和输出流数据,在服务端通过一个阻塞方法accept来不断接受客户端的连接请求,并使用读写流等操作对客户端的数据进行读写操作处理。

步骤:

客户端:1、创建客户端Socket套接字,并将其与目的主机信息进行绑定

2、从数据源中读取数据并写入到套接字输出流中

3、读取套接字中由服务端传过来的确认信息

4、关闭套接字。

服务端:

1、创建服务端socket服务,并监听一个端口。

2、服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象。

3、可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。

4、如果通讯结束,关闭资源。注意:要先关客户端,再关服务端。

实例:校验登录名,服务端利用多线程技术,不断接收从不同客户端的连接请求,对每一个请求建立新的校验线程,判断用户名的正确性。

import java.net.*;
import java.io.*;
class LoginClient 
{
	public static void main(String[] args) 
	{
		try
		{
			//创建客户端套接字对象,并指定服务端地址信息
			Socket s=new Socket("192.168.1.158",5003);
			//创建读取键盘录入数据的流对象
			BufferedReader bufR=new BufferedReader(new InputStreamReader(System.in));
			//获取套接字输出流对象,将键盘数据写入到输出流
			PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
			//获取套接字输入流对象,读取服务端的反馈信息
			BufferedReader buffReader=new BufferedReader(new InputStreamReader(s.getInputStream()));
			String strLine=null;
			//最多有三次输入用户名的机会
			for(int i=0;i<3;i++)
			{
				strLine=bufR.readLine();
				if(strLine==null)
					break;
				pw.println(strLine);

				//读取服务端反馈信息
				String strBack=buffReader.readLine();
				if(strBack.contains("successed"))
				{
					System.out.println(strBack);
					break;
				}
				System.out.println(strBack);
			}
			s.shutdownOutput();
			s.close();
			
		}
		catch (Exception e)
		{
			throw new RuntimeException("Login failed!");
		}
	}
}

class LoginServer
{
	public static void main(String[] args)throws Exception
	{
		ServerSocket ss=new ServerSocket(5003);
		while(true)
		{
			Socket s=ss.accept();
			new Thread(new LoginThread(s)).start();
		}
	}
}
class LoginThread implements Runnable
{
	private Socket s;
	LoginThread(Socket s)
	{
		this.s=s;
	}
	public void run()
	{
		String ip=s.getInetAddress().getHostAddress();
		try
		{
			

			for(int i=0;i<3;i++)
			{
				//读取硬盘中保存的用户数据信息
				BufferedReader bufR=new BufferedReader(new FileReader("user.txt"));
				BufferedReader bufS=new BufferedReader(new InputStreamReader(s.getInputStream()));

				PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
				String names=null;
				String name=bufS.readLine();
				//匹配结束标志
				boolean bMatch=false;
				while((names=bufR.readLine())!=null)
				{
					if(name.equals(names))
					{
						bMatch=true;
						break;
					}
		
				}
				if(bMatch)
				{
					System.out.println(ip+"Login!");
					pw.println("Login successed!");
					break;
				}
				else
				{
					System.out.println(ip+"failed!");
					pw.println("Login failed!");
				}
			}
			s.close();
			
		}
		catch (Exception e)
		{
			throw new RuntimeException("Login failed!");
		}
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值