Java之网络编程应用(一:基础篇)
声明:本文根据慕课网汤小洋老师的精品课程整理来的:慕课网
什么事Socket?
IP地址和端口号组成了所谓的socket,socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。
Java中的网络支持?
针对网络通信的不同层次,Java提供的网络功能有四大类:
- InetAddress:用于标识网上的硬件资源。
- URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据。
- Sockets:使用TCP协议实现网络通信的Socket相关的类。
- Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通信。
Java中的InetAddress应用
1 public class TestInetAddress { 2 3 public static void main(String[] args) throws UnknownHostException { 4 //获取本机的InetAddress实例 5 InetAddress address = InetAddress.getLocalHost(); 6 System.out.println("计算机名:"+address.getHostName()); 7 System.out.println("IP地址:"+address.getHostAddress()); 8 byte[] bytes = address.getAddress();//获取字节数组形式的IP地址 9 System.out.println("字节数组形式的IP:"+Arrays.toString(bytes)); 10 System.out.println("address:"+address);//直接输出InetAddress对象 11 } 12 13 }
Java中的URL应用
1 public class TestUrl { 2 public static void main(String[] args) { 3 try { 4 //创建一个URL实例 5 URL imooc = new URL("http://www.imooc.com"); 6 //?后面表示参数,3后面表示锚点 7 URL url = new URL(imooc,"/index.html?username=tom#test"); 8 System.out.println("协议:"+url.getProtocol()); 9 System.out.println("主机名称:"+url.getHost()); 10 //如果未指定端口号,则使用默认的端口号,此时getPort()方法返回值为-1 11 System.out.println("端口号:"+url.getPort()); 12 System.out.println("文件路径:"+url.getPath()); 13 System.out.println("文件名:"+url.getFile()); 14 System.out.println("相对路径:"+url.getRef()); 15 System.out.println("查询字符串:"+url.getQuery()); 16 } catch (MalformedURLException e) { 17 e.printStackTrace(); 18 } 19 } 20 }
使用URL读取网页内容:
1.通过URL对象的openStream()方法可以得到指定资源的输入流。
2.通过输入流可以读取,访问网络上的数据。
1 public class TestUrlReader { 2 public static void main(String[] args) { 3 try { 4 //创建一个URL实例 5 URL url = new URL("http://www.baidu.com"); 6 //通过url的openStream()方法获取URL对象所表示的资源的字节输入流 7 InputStream is = url.openStream(); 8 //将字节输入流转换为字符输入流 9 InputStreamReader isr = new InputStreamReader(is,"utf-8"); 10 //为字符输入流添加缓冲 11 BufferedReader br = new BufferedReader(isr); 12 //读取数据 13 String data = br.readLine(); 14 while(data!=null){//循环读取数据 15 System.out.println(data); 16 data = br.readLine(); 17 } 18 //关闭流 19 br.close(); 20 isr.close(); 21 is.close(); 22 } catch (MalformedURLException e) { 23 e.printStackTrace(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 } 28 }
Java的Socket通信:
Java基于tcp协议实现网络通信的类有两个:
- 客户端的Socket类
- 服务器端的ServerSocket类
使用Java的socket通信实现用户登录响应功能:
服务器端:
1 public class Server { 2 public static void main(String[] args) { 3 try { 4 //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 5 ServerSocket serverSocket = new ServerSocket(8888); 6 //2.调用accept()方法开始监听,等待客户端的连接 7 System.out.println("***服务器即将启动,等待客户端的连接****"); 8 Socket socket = serverSocket.accept(); 9 //3.获取输入流,并读取客户端信息 10 InputStream is = socket.getInputStream();//字节输入流 11 InputStreamReader isr = new InputStreamReader(is);//将字节流转换成字符流 12 BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲 13 14 String info = null; 15 while((info=br.readLine())!=null){ 16 System.out.println("我是服务器,客户端说:"+info); 17 } 18 //4.获取输出流,响应客户端请求 19 OutputStream os = socket.getOutputStream(); 20 PrintWriter pw = new PrintWriter(os);//包装为打印流 21 pw.write("欢迎您"); 22 pw.flush();//调用flush方法将缓冲输出 23 24 //5.关闭资源 25 pw.close(); 26 os.close(); 27 br.close(); 28 isr.close(); 29 is.close(); 30 socket.close(); 31 serverSocket.close(); 32 } catch (IOException e) { 33 e.printStackTrace(); 34 } 35 } 36 }
客户端:
1 public class Client { 2 public static void main(String[] args) { 3 try { 4 //1.创建客户端socket,指定服务器地址和端口 5 Socket socket = new Socket("localhost",8888); 6 //2.获取输出流,向服务器端发送信息 7 OutputStream os = socket.getOutputStream();//字节输出流 8 PrintWriter pw = new PrintWriter(os);//将输出流包装成打印流 9 pw.write("用户名:admin 密码:123"); 10 pw.flush(); 11 socket.shutdownOutput();//关闭输出流 12 //3.获取输入流,用来读取服务器端的响应信息 13 InputStream is = socket.getInputStream(); 14 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 15 String info = null; 16 while((info=br.readLine())!=null){ 17 System.out.println("我是客户端,服务器端说:"+info); 18 } 19 //4.关闭资源 20 br.close(); 21 is.close(); 22 pw.close(); 23 os.close(); 24 socket.close(); 25 } catch (UnknownHostException e) { 26 e.printStackTrace(); 27 } catch (IOException e) { 28 e.printStackTrace(); 29 } 30 } 31 }
应用多线程来实现服务器与多客户端之间的通信:
实现步骤:
- 服务器端创建ServerSocket,循环调用accept()等待客户端连接。
- 客户端创建一个Socket并请求和服务器端连接。
- 服务器端接受客户端的请求,创建socket与该客户建立专线连接。
- 建立连接的两个socket在一个单独的线程上对话。
- 服务器端继续等待新的连接。
创建线程类:
1 public class ServerThread extends Thread{ 2 //和本线程相关的Socket 3 Socket socket = null; 4 public ServerThread(Socket socket){ 5 this.socket = socket; 6 } 7 //线程执行的操作,响应客户端的请求 8 public void run() { 9 //获取输入流,并读取客户端信息 10 InputStream is = null; 11 InputStreamReader isr = null; 12 BufferedReader br = null; 13 OutputStream os = null; 14 PrintWriter pw = null; 15 try { 16 is = socket.getInputStream(); 17 // 字节输入流 18 isr = new InputStreamReader(is);// 将字节流转换成字符流 19 br = new BufferedReader(isr);// 为输入流添加缓冲 20 String info = null; 21 while ((info = br.readLine()) != null) { 22 System.out.println("我是服务器,客户端说:" + info); 23 } 24 socket.shutdownInput();//关闭输入流 25 // 4.获取输出流,响应客户端请求 26 os = socket.getOutputStream(); 27 pw = new PrintWriter(os);// 包装为打印流 28 pw.write("欢迎您"); 29 pw.flush();// 调用flush方法将缓冲输出 30 } catch (IOException e1) { 31 e1.printStackTrace(); 32 }finally{ 33 // 5.关闭资源 34 try { 35 if(pw!=null) 36 pw.close(); 37 if(os!=null) 38 os.close(); 39 if(br!=null) 40 br.close(); 41 if(isr!=null) 42 isr.close(); 43 if(is!=null) 44 is.close(); 45 if(socket!=null) 46 socket.close(); 47 } catch (IOException e) { 48 e.printStackTrace(); 49 } 50 } 51 } 52 }
修改服务器端代码
1 public class Server1 { 2 public static void main(String[] args) { 3 try { 4 // 1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 5 ServerSocket serverSocket = new ServerSocket(8888); 6 Socket socket = null; 7 //记录客户端的数量 8 int count =0; 9 System.out.println("***服务器即将启动,等待客户端的连接****"); 10 //循环监听等待客户端的监听 11 while(true){ 12 //调用accept()方法开始监听,等待客户端的连接 13 socket = serverSocket.accept(); 14 //创建一个新的线程 15 ServerThread serverThread = new ServerThread(socket); 16 //启动线程 17 serverThread.start(); 18 count++;//统计客户端数量 19 System.out.println("客户端的数量:"+count); 20 //获取客户端IP 21 InetAddress address = socket.getInetAddress(); 22 System.out.println("当前客户端的IP是:"+address.getAddress()); 23 } 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 } 28 }