title: Java中的网络支持Socket应用 date: 2019-05-04 14:00:00
Java中的网络支持Socket应用
前言:
单机的程序终究会被淘汰的,所以还是要让你的程序软件赋予联网通信的能力,恰恰Java提供了Socket这种功能强大的类,方便Java程序员进行网络应用开发。
准备工作:
首先你得先学一下网络的基础知识,IP地址,端口,网络协议
IP地址:
为了实现网络中不同计算机之间的通信,每台机器都必须有一个唯一的标识---IP地址。IP地址格式:数字型。如192.168.0.1,想深入学习可以看看《探索Linux的网络世界》
端口:
用于区分不同应用程序;端口号范围为0~65535,其中0~1023为系统所保留,常见端口:http:80 ;ftp:21; telnet: 23
网络协议:
IP地址和端口号组成所谓的Socket,Socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础
理解完上述的网络知识的基础,我们来学一下Java中的网络支持,针对网络通信的不同层次Java提供的网络功能有四大类:
Java提供的网络功能有四大类:
InetAddress:
用于标识网络上的硬件资源,通俗来说,用来标识IP地址的
URL:
统一资源定位符,通过URL可以直接读取或写入网络上的数据
Socket:
使用TCP协议实现网络通信的Socket相关的类
Datagram:
使用UDP协议,将数据保存在数据报中,通过网络进行通信
简单的说了一下Java提供的网络功能有四大类的通俗解析,下面我们看一下他们的用,话不多说,我贴上代码,代码实现简单,编程开发中遇到建议查看Java文档中具体介绍
InetAddress:
public class demo1{ /* *java中InetAddress的应用 */ public static void main(String[]args)throws Unknow HostException{ //获取本机的InetAddress实例 InetAddress address=InetAddress.getLocalHost(); System.out.println("计算机名"+address.getHostName()); System.out.println("IP地址"+address.getHostAddress()); //获取字节数组形式的IP地址 byte [] bytes=address.getaddress(); System.out.println("字节数组形式的IP"+Arrays.toString(bytes)); //直接输出InetAddress对象 System.out.println(address); //根据机器名获取InetAddress实例 InetAddresss address2=InetAddress.getByName("hkq"); System.out.println("计算机名"+address2.getHostName()); System.out.println("IP地址"+address2.getHostAddress()); //根据IP获取InetAddress实例 InetAddresss address2=InetAddress.getByName("1.1.1.10"); System.out.println("计算机名"+address2.getHostName()); System.out.println("IP地址"+address2.getHostAddress()); } }
java中URL的应用
public class demo2{ /* *java中URL的应用 *URL由两部分组成:协议名称和资源名称,中间用冒号隔开 *在1java.net包中提供了URL类来表示URL */ public static void main(String[]args)throws Unknow HostException{ try{ //创建一个URL实例 URL baidu=new URL("http://www.baidu.com"); //?后面表示参数,#后面表示锚点 URL url=new URL(baidu,"/index.html?username=hkq#test"); System.out.println("协议: "+url.getProtocol()); System.out.println("主机: "+url.getHost()); //如果未指定端口号,则使用默认的端口号,此时getPort()方法返回值为-1 System.out.println("端口:"+ url.getPort()); System.out.println("文件路径"+url.getPath()); System.out.println("文件名"+url.getFile()); System.out.println("相对路径"+url.getRef()); System.out.println("查询字符串"+url.getQuery()); /* *使用URL读取网页内容 *通过URL对象的openStream()方法可以得到指定资源的输入流 *通过输入流可以读取、访问网络上的数据 */ //创建一个URL实例 URL url=new URL("http:hongkaiqing.cn"); //通过URL的openStream方法获取URL对象所表示的资源的字节输入流 InputStream is =url.openStream(); //将字节输入流转换为字符 InputStreamReader isr=new InputStreamReader(is,"utf-8"); //为字符输入流添加缓冲,添加读取的效率 BufferedReader br=new BufferedReader(isr); //定义string类型的data接收读取数据 String datta =br.readLine(); //循环读取数据 while(data!=null){ //输出数据 System.out.println(data); //再读取下一行数据 data=br.readLine(); } //关闭资源 br.close(); isr.close(); is.close(); }cath (MalformedURLException e){ e.printStackTrace(); }cath (MalformedURLException e){ e.printStackTrace(); } } }
Socket
刚才有说,Socket是使用TCP协议实现网络通信的Socket相关的类,那啥是TCP呢?欢迎你百度一下,其实TCP协议是面向连接、可靠的、有序的......Socket通信是以字节流方式发送数据基于TCP协议实现网络通信的类,客户端的Socket类;服务器端的ServerSocket类,具体流程嘛?我们上图介绍一下:
what?看到这种流程,感觉是蒙圈的,通俗来说,其实这个类是用于客户端和服务器端通信的,我想想怎么理解这个呢!!!客户端和服务器端是什么意思啊?我也是接触了才想明白这个知识点,客户端通俗来说就是你电脑浏览的网页页面,用到的软件,例如:微信、QQ...
服务器端通俗来说就是一台远程的电脑,一台不会关机的电脑,它提供了两个IP供你访问,一个公网IP,一个内网IP(这个暂时不用管),公网IP是你登录这台远程电脑的唯一标识...其他你不懂就百度吧,我不想打字了
我怎么扯远了,哎,我们谈回这个Socket类,我们用一个登录的小案例,尝试理解这个Socket类
实现登录小案例:通俗来说就是客户端发送账号密码等用户信息给服务器端,服务器端根据客户端请求进行响应,
服务器端实现步骤;
1.创建ServerSocket对象,绑定监听端口
2.通过accept()方法监听客户端请求
3.连接建立后,通过输入流读取客户端发送的请求信息
4.通过输出流向客户端发送响应信息
5.关闭相关资源
客户端实现步骤;
1.创建Socket对象,指明需要连接的服务器的地址和端口号
2.连接建立后,通过输出流读取服务器端发送请求信息
3.通过输入流获取服务器端响应信息
4.关闭相关资源
大概实现的步骤就这些了....,下面贴上我实现的简陋代码,servert类代表实现服务器端代码,client类代表客户端实现代码...
package SinginScoket; import java.io.BufferedReader; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; /*** * 基于TCP协议的Socket,实现用户登录 * 服务器端 * @author hkq * */ public class Servert { public static void main(String[] args) { try { //1.创建一个服务器端的Socket,即ServerSocket,指定绑定的端口,并监听此端口 ServerSocket serverSocket=new ServerSocket(8088); //2.调用accept()方法开始监听,等待客户端的连接 System.out.println("服务器端启动,等待客户端连接"); Socket socket= serverSocket.accept(); //3.获取字节输入流,并读取客户端信息 InputStream is=socket.getInputStream(); //4.将字节流装换为字符流,好处是提高读取的效率 InputStreamReader isr=new InputStreamReader(is); //5.搭配使用,为字符输入流添加缓冲 BufferedReader br=new BufferedReader(isr); //6.定义String类型的info,循环读取客户端信息并在控制台输出 String info=null; while ((info=br.readLine())!=null) { System.out.println("服务器端接收到客户端数据为:"+info); } //7.关闭socket输入流 socket.shutdownInput(); //8.获取输出流,响应客户端的请求 OutputStream os =socket.getOutputStream(); //将字节输出流转换为打印输出流 PrintWriter pw=new PrintWriter(os); //服务器端向客户端发送响应信息 pw.write("登录成功,欢迎你"); //调用flush()方法刷新缓存 pw.flush(); //9.关闭资源 pw.close(); os.close(); br.close(); isr.close(); is.close(); socket.close(); serverSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
客户端:
package SinginScoket; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; /*** * 客户端 * @author hkq * */ public class Client { public static void main(String[] args) { try { //1.创建客户端Socket,指定`服务器地址和端口 Socket socket=new Socket("127.0.0.1", 8088); //2.连接建立后,通过获取字节输出流读取服务器发送信息 OutputStream os =socket.getOutputStream(); //将字节输出流转换为打印输出流 PrintWriter pw=new PrintWriter(os); //向服务器端发送用户信息请求 pw.write("用户名: admin;密码: 123"); //刷新缓存 pw.flush(); //关闭scoket的输出流 socket.shutdownOutput(); //获取输入流,并读取服务器端的响应信息 InputStream is=socket.getInputStream(); //将字节流装换为字符流,好处是提高读取的效率 InputStreamReader isr=new InputStreamReader(is); //搭配使用,为字符输入流添加缓冲 BufferedReader br=new BufferedReader(isr); //定义String类型的info,循环读取服务器信息响应并在控制台输出 String info=null; while ((info=br.readLine())!=null) { System.out.println("客户端接收到服务器端数据为:"+info); } //关闭所有资源 br.close(); is.close(); pw.close(); os.close(); socket.close(); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
运行的时候,一定是服务器端的代码先运行,因为客户端的代码先运行会因为找不到服务器端的出现错误提示.....
Datagram:
使用UDP协议,将数据保存在数据报中,通过网络进行通信。什么是UDP协议?百度给的解析:UDP协议(用户数据报协议)是无连接、不可靠、无序的,以数据报作为数据传输的载体进行数据传输时,首先需要将要传输的数据定义成数据报,在数据报中指明数据所达到的Socket(主机地址和端口号),然后再将数据报发出去...什么鬼啊?我通俗不了啊,算了,我们还是先看这个Datagram类的用法吧,它提供了两个相关操作类:
DatagramPacket: 表示数据报包
DatagramSocket:进行端到端通信的类
我们还是用一个登录案例了解一下这个Datagram类所使用的UDP编程
服务器端实现步骤:
1.创建DatagramSocket,指定端口号
2.创建DatagramPacket
3.接收客户端发送的数据信息
4.读取数据
package UDPsingin; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; /*** * 服务器端,实现UDP的用户登录 * @author hkq * */ public class UDPserver { public static void main(String[] args) throws IOException { /*** * 服务器端接收客户端发送的数据 */ //1.创建服务端DatagramSocket,指定端口 DatagramSocket socket=new DatagramSocket(8082); //2.创建数据报,用于接收客户端发送的数据 //创建字节数组,指定接收数据包的大小 byte [] data=new byte[1024]; DatagramPacket packet=new DatagramPacket(data, data.length); System.out.println("服务器端已启动,等待客户端连接"); //3.接收客户端发送的数据 //此方法在接收到数据报之前会一直阻塞 socket.receive(packet); //4.读取数据 String info=new String(data,0,packet.getLength()); System.out.println("这里是服务器,客户端对我说:"+info); /*** * 服务器端向客户端响应数据 */ //1.定义客户端的地址、端口、数据 InetAddress address=packet.getAddress(); int port=packet.getPort(); byte[]data2="登录成功".getBytes(); //2.创建数据报,包含响应的数据信息 DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port); //3.响应客户端,发送数据报 socket.send(packet2); //4.关闭资源 socket.close(); } }
客户端实现步骤:
1.定义发送信息(服务器地址,端口号)
2.创建DatagramPacke数据报t,包含将要发送的信息
3.创建DatagramSocket对象,实现数据发送
4.发送数据
package UDPsingin; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; /*** * 客户端,实现UDP的用户登录 * @author hkq * */ public class UDPClient { /*** * 向服务器端发送数据 * @param args * @throws IOException */ public static void main(String[] args) throws IOException { //1.定义服务器的地址、端口号、数据 InetAddress address=InetAddress.getByName("127.0.0.1"); int port=8082; byte []data="用户名: admin;密码: 456".getBytes(); //2.创建数据报,包含发送的数据信息 DatagramPacket packet=new DatagramPacket(data, data.length, address, port); //3.创建DatagramSocket对象 DatagramSocket socket=new DatagramSocket(); //4.向服务器发送数据报 socket.send(packet); /*** * 接收服务器端响应的数据 * */ //1.创建数据报,用于接收服务器端响应的数据 byte[] data2=new byte[1024]; DatagramPacket packet2=new DatagramPacket(data2, data2.length); //2.接收服务器端响应的数据 socket.receive(packet2); //3.读取数据 String reply=new String(data2, 0, packet2.getLength()); System.out.println("这里是客户端,服务器反馈信息:"+reply); //关闭资源 socket.close(); } }
运行的时候,一定是服务器端的代码先运行,因为客户端的代码先运行会因为找不到服务器端的出现错误提示…..
重点掌握:
Socket通信原理,基于TCP的Socket通信