第十六章 网络编程

16、网络编程
16.1 网络编程概述 1课时
16.2 通讯要素 1课时
16.3 InetAddress类 1课时
16.4 TCP网络通信 1课时
16.5 UDP网络通信 1课时
16.6 NIO中的非阻塞式网络通信 1课时
16.7 URL编程 1课时

16-1 网络编程概述

16-2 网络通信要素

16-3 InetAddress类

InetAddress类的案例

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 一、要想实现网络通信,需要解决两个问题:
 * 1.如何准确的定位互联网上的一台或多台主机
 * 2.如何实现可靠而高效的数据传输
 * 
 * 二、网络通信的两个要素:
 * 1.使用IP地址,定位网络中的主机
 * 2.遵循相关的网络通信协议
 * 
 * 三、针对要素一:
 * 1.IP:一个ip地址,对应着网络中的一台主机。 "192.168.20.16"   "127.0.0.1"--本地回路地址
 *   使用InetAddress类来代表IP,一个InetAddress类的对象,就代表着一个具体的ip地址。
 * 
 * 2.如何实例化InetAddress:①getByName(String hostName) ②getLocalHost()
 * 		
 * 3.域名: www.baidu.com   www.jd.com   www.mi.com  www.vip.com
 *        www.facebook.com
 *        localhost对应着127.0.0.1
 * 
 * 4.InetAddress类的常用方法:getHostName() / getHostAddress()
 * 
 * 
 * 5.端口号标识正在计算机上运行的进程(程序)
 *  注意:不同的进程有不同的端口号
 *  常见的端口号: http:80   tomcat : 8080   mysql:3306  oracle:1521等
 * 
 */
public class InetAddressTest {
	public static void main(String[] args) {
		
		//1.实例化
		try {
			//getByName()
			InetAddress inetAddress = InetAddress.getByName("192.168.10.16");
			System.out.println(inetAddress);
			
			InetAddress inetAddress1 = InetAddress.getByName("www.tzy.com");
			System.out.println(inetAddress1);//www.tzytzy.top/100.151.2.166
			//getLocalHost()
			InetAddress localAddress = InetAddress.getLocalHost();
			System.out.println(localAddress);
			
			
			//2.两个方法
			System.out.println(inetAddress1.getHostName());//www.tzytzy.top
			
			System.out.println(inetAddress1.getHostAddress());//100.151.2.166
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		
	}
}

16-4 TCP网络通信

TCP案例

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

import org.junit.Test;

//使用TCP的网络通信:1.客户端发送内容给服务端,服务端将内容打印到控制台上。
public class TCPTest1 {

	// 客户端
	@Test
	public void client() {
		Socket socket = null;
		OutputStream os = null;
		try {
			// 1.创建一个Socket,指明服务器端的ip及端口号
			socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);

			// 2.通过socket获取一个输出流
			os = socket.getOutputStream();
			// 3.输出数据
			os.write("我是客户端要发送的数据".getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (os != null) {
				// 4.关闭资源
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
			if (socket != null) {
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}

	}

	// 服务器端
	@Test
	public void server() {
		ServerSocket serverSocket = null;
		Socket socket = null;
		InputStream is = null;
		ByteArrayOutputStream baos = null;
		try {
			//1.创建serverSocket,需要指明自己的端口号
			serverSocket = new ServerSocket(9090);
			//2.接口客户发送的Socket
			socket = serverSocket.accept();
			//3.读取发送来的数据,并显示在控制台上
			is = socket.getInputStream();
			baos = new ByteArrayOutputStream();
			byte[] buffer = new byte[20];
			int len;
			while ((len = is.read(buffer)) != -1) {
				baos.write(buffer, 0, len);
			}
			System.out.print(baos.toString());
			System.out.println("收到了来自于" + socket.getInetAddress().getHostAddress() + "的数据");
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//4.关闭资源
			if (baos != null) {
				try {
					baos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
			if (socket != null) {
				try {
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
			if (serverSocket != null) {

				try {
					serverSocket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}

	}

}

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket;
import org.junit.Test;

//使用TCP的网络通信:2.客户端发送文件给服务器端,服务器端保存在本地。

public class TCPTest2 {
	
	//客户端
	//异常应该使用try-catch-finally处理
	@Test
	public void client() throws Exception{
		//1.
		Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
		//2.
		OutputStream os = socket.getOutputStream();
		//3.
		FileInputStream fis = new FileInputStream("beauty.jpg");
		//4.读写数据
		byte[] buffer = new byte[20];
		int len;
		while((len = fis.read(buffer)) != -1){
			os.write(buffer, 0, len);
			
		}
		//5.
		fis.close();
		os.close();
		socket.close();
		
	}
	
	//服务器端
	@Test
	public void server() throws IOException{
		//1.
		ServerSocket serverSocket = new ServerSocket(9090);
		
		//2.
		Socket socket = serverSocket.accept();
		//3.
		InputStream is = socket.getInputStream();
		
		//4.
		FileOutputStream fos = new FileOutputStream("beauty1.jpg");
		
		//5.读写数据
		byte[] buffer = new byte[20];
		int len;
		while((len = is.read(buffer)) != -1){
			fos.write(buffer, 0, len);
		}
		
		//6.
		fos.close();
		is.close();
		socket.close();
		serverSocket.close();
	}
}

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket;
import org.junit.Test;

//使用TCP的网络通信:3.客户端发送文件给服务器端,服务器端保存在本地。同时,服务器发送反馈给客户端
public class TCPTest3 {
	// 客户端
	// 异常应该使用try-catch-finally处理
	@Test
	public void client() throws Exception {
		// 1.
		Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
		// 2.
		OutputStream os = socket.getOutputStream();
		// 3.
		FileInputStream fis = new FileInputStream("beauty.jpg");
		// 4.读写数据
		byte[] buffer = new byte[20];
		int len;
		while ((len = fis.read(buffer)) != -1) {
			os.write(buffer, 0, len);

		}
		
		//表明,输出结束
		socket.shutdownOutput();
		
		//接收来自于服务器端的数据
		//练习:使用ByteArrayOutputStream更合适
		InputStream is = socket.getInputStream();
		byte[] buf = new byte[200];
		int len1;
		while((len1 = is.read(buf)) != -1){
			System.out.print(new String(buf,0,len1));
		}
		
		
		// 5.
		is.close();
		fis.close();
		os.close();
		socket.close();

	}

	// 服务器端
	@Test
	public void server() throws IOException {
		// 1.
		ServerSocket serverSocket = new ServerSocket(9090);

		// 2.
		Socket socket = serverSocket.accept();
		// 3.
		InputStream is = socket.getInputStream();

		// 4.
		FileOutputStream fos = new FileOutputStream("beauty2.jpg");

		// 5.读写数据
		byte[] buffer = new byte[20];
		int len;
		while ((len = is.read(buffer)) != -1) {
			fos.write(buffer, 0, len);
		}
		
		System.out.println("hello!");
		
		//发送反馈给客户端
		OutputStream os = socket.getOutputStream();
		os.write("我收到了你的照片,很漂亮!".getBytes());
		

		// 6.
		os.close();
		fos.close();
		is.close();
		socket.close();
		serverSocket.close();
	}
}

16-5 UDP网络通信

发送端
DatagramSocket ds = new DatagramSocket();
byte[] by = “hello,xxx.com”.getBytes();
DatagramPacket dp = new DatagramPacket(by,0,by.length,
		InetAddress.getByName(“127.0.0.1”),10000);
ds.send(dp);
ds.close();
接收端

在接收端,要指定监听的端口。

DatagramSocket ds = new DatagramSocket(10000);
byte[] by = new byte[1024];
DatagramPacket dp = new DatagramPacket(by,by.length);
ds.receive(dp);
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str+"--"+dp.getAddress());
ds.close();

UDP案例

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

import org.junit.Test;

//UDP的网络通信
public class UDPTest {

	//发送端
	@Test
	public void sender() throws Exception{
		DatagramSocket socket = new DatagramSocket();
		
		//提供数据报。在数据报中封装要发送的数据,以及要发送到的接收端的ip地址和端口号。
		byte[] buf = "我是UDP方式发送的导弹".getBytes();
		DatagramPacket pack = new DatagramPacket(buf, 0, buf.length, InetAddress.getByName("127.0.0.1"), 8989);
		
		socket.send(pack);
		
		socket.close();
		
	}
	
	//接收端
	@Test
	public void receiver() throws Exception{
		
		DatagramSocket socket = new DatagramSocket(8989);
		byte[] buf = new byte[200];
		DatagramPacket pack = new DatagramPacket(buf, 0, buf.length);
		
		socket.receive(pack);
		//pack.getData():获取数据报中封装的数组
		//pack.getLength():获取写入到数组中的数据的长度
		System.out.println(new String(pack.getData(), 0, pack.getLength()));
		
		socket.close();
	}
}

16-6 NIO中的非阻塞式网络通信

NIO实现阻塞式

    import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import org.junit.Test;

//TCP网络编程1:使用NIO中的Channel + Buffer 实现客户端给服务器端发送文件.
public class BlockingNIOTest {
	
	@Test
	public void client() throws Exception{
		InetAddress addr = InetAddress.getByName("127.0.0.1");
		SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(addr, 9090));
		
		FileChannel fileChannel = FileChannel.open(Paths.get("beauty.jpg"), StandardOpenOption.READ);
		
		//使用Channel实现数据的读写
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
		while(fileChannel.read(byteBuffer) != -1){
			byteBuffer.flip();
			socketChannel.write(byteBuffer);
			byteBuffer.clear();
		}
		
		fileChannel.close();
		socketChannel.close();
		
		
	}
	
	@Test
	public void server() throws Exception{
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		//绑定端口号
		serverSocketChannel.bind(new InetSocketAddress(9090));
		
		SocketChannel socketChannel = serverSocketChannel.accept();
		
		//使用FileChannel和SocketChannel实现数据的读写
		FileChannel fileChannel = FileChannel.open(Paths.get("beauty3.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
		while(socketChannel.read(byteBuffer) != -1){
			byteBuffer.flip();
			fileChannel.write(byteBuffer);
			byteBuffer.clear();
		}
		
		fileChannel.close();
		socketChannel.close();
		serverSocketChannel.close();
		
	}
}

import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.file.Paths; import java.nio.file.StandardOpenOption;
import org.junit.Test;

//TCP网络编程2:使用NIO中的Channel + Buffer 实现客户端给服务器端发送文件,同时,服务器在接收完毕以后,给予反馈
public class BlockingNIOTest1 {
	
	
	@Test
	public void client() throws Exception{
		InetAddress addr = InetAddress.getByName("127.0.0.1");
		SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(addr, 9090));
		
		FileChannel fileChannel = FileChannel.open(Paths.get("beauty.jpg"), StandardOpenOption.READ);
		
		//使用Channel实现数据的读写
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
		while(fileChannel.read(byteBuffer) != -1){
			byteBuffer.flip();
			socketChannel.write(byteBuffer);
			byteBuffer.clear();
		}
		
		//关闭数据的输出
		socketChannel.shutdownOutput();
		
		
		//接收来自于服务器端的数据
		socketChannel.read(byteBuffer);
		byteBuffer.flip();
		System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit()));
		byteBuffer.clear();//可有可无
		
		
		fileChannel.close();
		socketChannel.close();
		
		
	}
	
	@Test
	public void server() throws Exception{
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		//绑定端口号
		serverSocketChannel.bind(new InetSocketAddress(9090));
		
		SocketChannel socketChannel = serverSocketChannel.accept();
		
		//使用FileChannel和SocketChannel实现数据的读写
		FileChannel fileChannel = FileChannel.open(Paths.get("beauty4.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
		while(socketChannel.read(byteBuffer) != -1){
			byteBuffer.flip();
			fileChannel.write(byteBuffer);
			byteBuffer.clear();
		}
		
		//服务器端在接收完毕数据以后,发送反馈给客户端
		byteBuffer.put("人家已收到了你的情意,么么".getBytes());
		byteBuffer.flip();
		socketChannel.write(byteBuffer);
		byteBuffer.clear();//可有可无
		
		
		fileChannel.close();
		socketChannel.close();
		serverSocketChannel.close();
		
	}
	
}

NIO实现非阻塞式

/**
 * 使用NIO实现非阻塞式的TCP的网络传输:实现客户端给服务器端发送文件,同时,服务器在接收完毕以后,给予反馈
 * 
 * 1.选择器(Selector) 是 SelectableChannel 对象的多路复用器
 * 2.Selector 可以同时监控多个 SelectableChannel 的 IO 状况,也就是说,利用 Selector 
 * 可使一个单独的线程管理多个 Channel。
 * 3.Selector 是非阻塞 IO 的核心。
 * 4.SelectableChannel
 * 		|-----SocketChannel
 * 		|-----ServerSocketChannel
 * 		|-----DatagramChannel
 *
 */

public class NonBlockingNIOTest {
	
	@Test
	public void client() throws Exception{
		
		InetAddress addr = InetAddress.getByName("127.0.0.1");
		SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(addr, 9090));
		
		//设置当前Channel为非阻塞式的
		socketChannel.configureBlocking(false);
		
		Scanner scanner = new Scanner(System.in);
		
		//使用Channel实现数据的读写
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
		while(scanner.hasNext()){
			String line = scanner.nextLine();
			SocketAddress address = socketChannel.getLocalAddress();
			byteBuffer.put((address + "-" + new Date() + ":
" + line).getBytes());
			byteBuffer.flip();
			socketChannel.write(byteBuffer);
			byteBuffer.clear();
			
		}
		
		socketChannel.close();
		
	}
	
	
	@Test
	public void server() throws Exception{
		
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		
		//serverSocketChannel设置为非阻塞的
		serverSocketChannel.configureBlocking(false);
		//设置serverSocketChannel的端口号
		serverSocketChannel.bind(new InetSocketAddress(9090));
		
		//获取Selector
		Selector selector = Selector.open();
		//注册Selector,表明可以接收客户端的数据
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		SocketChannel socketChannel = null;
		while(selector.select() > 0){
			
			Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
			while(iterator.hasNext()){
				SelectionKey selectionKey = iterator.next();
				
				if(selectionKey.isAcceptable()){//表示当前可以接收客户端数据
					
					//接收到客户端发送来的socketChannel
					socketChannel = serverSocketChannel.accept();
					//设置socketChannel为非阻塞的
					socketChannel.configureBlocking(false);
					//注册
					socketChannel.register(selector, SelectionKey.OP_READ);
					
				}else if(selectionKey.isReadable()){//表示可以读取客户端的数据
					
					//读取SocketChannel中的数据
					socketChannel = (SocketChannel) selectionKey.channel();
					
					ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
					while(socketChannel.read(byteBuffer) > 0){
						byteBuffer.flip();
						System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit()));
						byteBuffer.clear();
						
					}
					
				}
					iterator.remove();
			}
		
			
		}
		
		socketChannel.close();
		serverSocketChannel.close();
		selector.close();
		
	}
	
}

import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Date; import java.util.Iterator; import java.util.Scanner;
import org.junit.Test;
//针对UDP,使用NIO实现非阻塞式的网络通信
public class NonBlockingNIOTest1 {
	
	@Test
	public void send() throws IOException{
		DatagramChannel dc = DatagramChannel.open();
		
		dc.configureBlocking(false);
		
		ByteBuffer buf = ByteBuffer.allocate(1024);
		
		Scanner scan = new Scanner(System.in);
		
		while(scan.hasNext()){
			String str = scan.nextLine();
			buf.put((new Date().toString() + ":
" + str).getBytes());
			buf.flip();
			dc.send(buf, new InetSocketAddress("127.0.0.1", 9898));
			buf.clear();
		}
		
		dc.close();
	}
	
	
	@Test
	public void receive() throws IOException{
		DatagramChannel dc = DatagramChannel.open();
		
		dc.configureBlocking(false);
		
		dc.bind(new InetSocketAddress(9898));
		
		Selector selector = Selector.open();
		
		dc.register(selector, SelectionKey.OP_READ);
		
		while(selector.select() > 0){
			Iterator<SelectionKey> it = selector.selectedKeys().iterator();
			
			while(it.hasNext()){
				SelectionKey sk = it.next();
				
				if(sk.isReadable()){
					ByteBuffer buf = ByteBuffer.allocate(1024);
					
					dc.receive(buf);
					buf.flip();
					System.out.println(new String(buf.array(), 0, buf.limit()));
					buf.clear();
				}
			}
			
			it.remove();
		}
		dc.close();
	}

}

16-7 URL编程

/**
 * 1.URL(Uniform Resource Locator):统一资源定位符,它表示 Internet 上某一资源的地址。
 * 
 * 2.举例:http://127.0.0.1:8080/examples/ym.jpg
 *       协议 网络主机  端口号 工程 文件
 * 
 * 3.如何实例化URL
 * 
 *
 */
public class URLTest {
	public static void main(String[] args) {
		HttpURLConnection conn = null;
		InputStream is = null;
		FileOutputStream fos = null;
		try {
			//1.实例化
//			URL url = new URL("http://127.0.0.1:8080/examples/ym.jpg?name=Tom");
			URL url = new URL("http://127.0.0.1:8080/examples/ym.jpg");
			
			//2.常用方法
			/*
			public String getProtocol(  )     获取该URL的协议名
			public String getHost(  )           获取该URL的主机名
			public String getPort(  )            获取该URL的端口号
			public String getPath(  )           获取该URL的文件路径
			public String getFile(  )             获取该URL的文件名
			public String getQuery(   )        获取该URL的查询名

			 */
//			System.out.println(url.getProtocol());
//			System.out.println(url.getHost());
//			System.out.println(url.getPort());
//			System.out.println(url.getPath());
//			System.out.println(url.getFile());
//			System.out.println(url.getQuery());
			
			//3.如何下载对应的url资源
			conn = (HttpURLConnection) url.openConnection();
			
			conn.connect();
			
			is = conn.getInputStream();
			fos = new FileOutputStream("ym1.jpg");
			byte[] buffer = new byte[1024];
			int len;
			while((len = is.read(buffer)) != -1){
				fos.write(buffer, 0, len);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(conn != null){
				conn.disconnect();
			}
			
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(fos != null){
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
		}
		
		
		
		
	}
}

原文地址:https://www.cnblogs.com/ttzzyy/p/9744737.html