黑马程序员——网络通信

所谓网络通信,就是在不同计算机间进行信息的沟通与交流,这就好比人与人之间进行的交流,人与人之间的交流需要使用的各种语言一样,同样计算机的交流有需要一种固定的交流语言,也就是通信协议。通信协议规范了计算机的通信标准。下面是对java语言的网络通信协议的学习。

 网络通信三要素:

1、  IP地址

IP是计算机在网络上的地址,因为网络上存在很多的计算机,当我们想要连接到某台计算机进行网络的通信时,的我们就可以通过IP地址寻找到我们想要连接的计算机。

IP地址是有四个占一个字节大小的整数组成,

例如: 193.165.2.3

特点:每一个数字不能大于255

由于IP地址是有一组数据组成,用户不方便记忆,所以产生了域名,域名是由一串用点分隔的名符组成的字符串,它代表网络上某一台计算机或计算机组的名称,与IP地址有着着相同的作用,那是不是可以说域名代替了IP地址呢?

其实我们的通信连接还是通过IP地址寻找连接的计算机,而域名只是IP地址的一个面具或者说别名,只是为了用户方便记忆。在连接某计算机是可以通过域名连接。

例:

http://blog.csdn.net

具体的工作原理:

通过ip地址连接网络的:


 

通过域名连接的计算机的工作原理:

要经过域名解析得到IP值


 

连接本机

连接本机的IP地址:127.0.0.1

主机名:localhost(通过这个名连接计算机不需要连接域名解析器)


InetAddress类

Java把IP地址也封装成了一个对象,该对象的IP地址类为InetAddress。该类提供了一些操作IP地址的方法:

getLocalHost() 返回本地主机IP对象

getHostName()获取此 IP 地址的主机名。

getHostAddress()返回 IP 地址字符串

getByName(String host) 在给定主机名的情况下确定主机的 IP 对象

InetAddress类应用 

 public static void main(String[] args) {
	 InetAddress IP;
	try {
		//获取本机IP对象
		IP = InetAddress.getLocalHost();
		
		System.out.println(IP);
		//获取本机主机名
		System.out.println(IP.getHostName());
		//获取本机IP
		System.out.println(IP.getHostAddress());
		//获取指定指定计算机的IP对象
		IP = InetAddress.getByName("www.hao123.com");
		//获取本机主机名
		System.out.println(IP.getHostName());
		//获取本机IP
		System.out.println(IP.getHostAddress());
		 
	} catch (UnknownHostException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	 

	}

}

2、端口

端口用于标识进程的逻辑地址,在计算机上运行的软件不仅仅是一个,可以同时运行多个软件,,但这些软件在网络上通信的时候,我们有了IP地址,可以寻找到对于的计算机,但是不能确定是与计算机上的那一个软件进行的通信,为了确定与相应的软件进行交流,还要确定端口,每一个运行的进程可以指定一个端口作为监听的端口,连接进来的计算机到指定的端口上就可以与相对应的软件进行交流,端口确保了各个进程间的通信不会出错。

有效端口:0 ~65535,系统使用或保留的端口是:0~ 1024

3、  传输协议

UDP协议:

UDP提供了无连接通信,在发送数据时,将数据及源和目的封装成数据包,我们只要把数据包发送出去,因为数据包中包中包含了目的地,不需要建立连接,所以数据发送出去以后,不能确保数据一定被接收到,如同手机发短信一样,短信发出以后不应定确保一定被手机接收到。可靠性较低,传输的数据会可能会丢失,如果使用UDP时应该考虑数据的部分丢失是否会影响较低的影响。

由于以数据包的形象传送数据,每个数据包的大小在限制在64k内,因无须连接,发送数据的效率较高,基于这个特点,UDP的通信一般用于视频会议,对于视频数据的部分丢失,不会影响,但是数据的传送量较大,要求效率高。

TCP协议:

TCP面向连接通信,通信的计算机之间要求建立一个连接进行通信,如同打电话,连接的连接手机必须同时接听,与UDP相反,数据的传输过程不会丢失数据,为可靠连接,适合大数据量交换。正因为通信要求建立连接,所以数据的传输效率较低。

 DatagramSocket类

此类表示用来发送和接收数据报包的套接字,用于UDP传输。数据报套接字是包投递服务的发送或接收。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

练习一、用UDP进行网络的通信。

/**
 * 
 *  俩个线程,一个发送数据,另一个接受数据
 *
 */
public class SocketTest {

	 
	public static void main(String[] args) {
		//运行两个线程
		 new Thread(new Socket1()).start();
		 new Thread(new Socket2()).start();
	}

}
class Socket1 implements Runnable
{
	DatagramSocket socket = null;
	@Override
	public void run() {
		 try {
			 //生成DatagramSocket对象
			 socket = new DatagramSocket();
			byte[] bytes = "tCPText".getBytes();
			//数据包,确定传输IP地址、端口号
			DatagramPacket packet = new DatagramPacket(bytes, 0,bytes.length,InetAddress.getByName("127.0.0.1"),10000);
			//发送数据
			socket.send(packet);
			socket.close();
			
		} catch ( Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		 
		 
		
	}
	
}

class Socket2 implements Runnable
{
	DatagramSocket socket =null;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			//指定程序的监听端口
			 socket = new DatagramSocket(10000);
			byte[] by = new byte[1024];
			//生成一个数据包用于接受数据
			DatagramPacket packet= new DatagramPacket(by,by.length);
			//接受数据
			socket.receive(packet);
			//获得数据
			String str = new String(packet.getData(),0,packet.getLength());
			System.out.println(str+"--"+packet.getAddress());
			socket.close();
		} catch ( Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	
}
运行效果图

 Socket类:

在java 中,Socket为网络服务提供的一种通信的机制,用于TCP传输,通信的两端都使用Socket建立连接,也就是说网络通信其实就是Socket对象间的通信。数据在两个Socket间通过IO传输。

练习二、用TCP进行网络的通信。


/**
 *  使用TCP协议完成一个客户端一个服务器。客户端从键盘输入读取一个字符串,发送到服务器。
 * 服务器接收客户端发送的字符串,反转之后发回客户端。客户端接收并打印。
 * 
 *
 */
public class Test10 {

	 
	public static void main(String[] args) {
	
	//服务器端的线程运行
    new Thread(new TCPServer()).start();
    //客户端的线程运行
    new Thread(new TCPClient()).start();
	}

}
/**
 * 为了在同一程序中运行客户端与服务器,俩个类分别实现Runable接口,在不同的线程中执行。
 * 
 *
 */
//客户端
class TCPClient  implements Runnable
{
	  private BufferedWriter TCPwriter;
	  private  BufferedReader TCPread;
	  private BufferedReader sysread;
	@Override
	public void run() {
		try {
			
			Socket socket = new Socket("127.0.0.1", 10002);
			 //建立TCP连接,得到读写流
			 TCPwriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			 TCPread = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			 //得到系统读入流
			 sysread =new BufferedReader(new InputStreamReader(System.in));
			 //系统读入
			String str = sysread.readLine();
			//发送字符串给服务器端
			TCPwriter.write(str);
			TCPwriter.newLine();//换行
			TCPwriter.flush();
			 //从服务器端读会数据
			String revstr = TCPread.readLine();
			//打印发回的字符串结果
			System.out.println("Client:"+revstr);
		} catch (UnknownHostException e) {
		 
			e.printStackTrace();
		} catch (IOException e) {
			 
			e.printStackTrace();
		}finally
		{
			//关闭IO流
				try {
					if(TCPread!=null)
					TCPread.close();
				} catch (IOException e) {
				 
					e.printStackTrace();
				}
				try {
					if(TCPwriter!=null)
					TCPwriter.close();
				} catch (IOException e) {
				 
					e.printStackTrace();
				}
				try {
					if(sysread!=null)
					sysread.close();
				} catch (IOException e) {
				 
					e.printStackTrace();
				}
		}
		
		
	}
	
}
//服务器端
class TCPServer implements Runnable
{
	  private BufferedWriter TCPwriter;
	  private  BufferedReader TCPread;
	@Override
	public void run() {
		 try {
			 //建立服务器端,监听10002端口;
			ServerSocket server = new ServerSocket(10002);
			//得到连接的读写流
			Socket socket =server.accept();
			TCPwriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			TCPread = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			//读取从客户端发来的数据
			String str = TCPread.readLine();
			//字符串反转
			char[] array = str.toCharArray();
			StringBuilder reverse = new StringBuilder();
			for(int i =array.length-1;i>=0;i--)
			reverse.append(array[i]);
			//把反转的字符串发送回给客户端
			TCPwriter.write(reverse.toString());
			TCPwriter.newLine();
			TCPwriter.flush();
			
		} catch (IOException e) {
			
			e.printStackTrace();
		}finally
		{
			//关闭IO流
			try {
				if(TCPread!=null)
				TCPread.close();
			} catch (IOException e) {
			 
				e.printStackTrace();
			}
			try {
				if(TCPwriter!=null)
				TCPwriter.close();
			} catch (IOException e) {
			 
				e.printStackTrace();
			}
		}
		
	}
	
}
运行效果图


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值