Java网络编程基础概述

目录

网络通信三要素

要素一:IP地址

IP地址操作类-InetAddress

要素二:端口号

要素三:协议

IP常用命令:

特殊lP地址:

UDP通信-快速入门

使用UDP实现一发一收

使用UDP实现多发多收

TCP通信-快速入门

TCP实现一发一收

TCP通信-多发多收消息

TCP通信-同时接受多个客户端消息

TCP通信-使用线程池优化

TCP实战案例——即时通信


网络通信三要素

要素一:IP地址

IP地址:设备在网络中的地址,是唯一的标识。

IP地址操作类-InetAddress

 

public class InetAddressDemo_01 {
	public static void main(String[] args) throws Exception {
		//1.获取本机地址对象
		InetAddress ip1 = InetAddress.getLocalHost();
		System.out.println(ip1.getHostName());
		System.out.println(ip1.getHostAddress());
		
		//2.获取域名ip对象
		InetAddress ip2 = InetAddress.getByName("www.jd.com");
		System.out.println(ip2.getHostName());
		System.out.println(ip2.getHostAddress());
  
		//3.获取公网ip对象
		InetAddress ip3 = InetAddress.getByName("221.14.7.3");
		System.out.println(ip3.getHostName());
		System.out.println(ip3.getHostAddress());
  
		//4.判断是否能通,ping 5s之前是否可通
		System.out.println(ip3.isReachable(5000));
	}
}

要素二:端口号

端口:应用程序在设备中唯一的标识。

端口号:标识正在计算机设备上运行的进程(程序),被规定为一个16位的二进制,范围是0~65535。

端口类型

周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)

注册端口:1024~49151,分配给用户进程或某些应用程序。(如:Tomcat占用8080,MySQL占用3306)

动态端口:49152到65535,之所以称为动态端口,是因为它一般不固定分配某种进程,而是动态分配。

要素三:协议

协议:数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。

网络通信协议:连接和通信数据的规则被称为网络通信协议

网络通信协议有两套参考模型

OSI参考模型:世界互联协议标准,全球通信规范,由于此模型过于理想化,未能在因特网上进行广泛推广。

TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

传输层的2个常见协议

TCP(Transmission Control Protocol) ︰传输控制协议

UDP(User Datagram Protocol):用户数据报协议

TCP协议特点

使用TCP协议,必须双方先建立连接,它是一种面向连接的可靠通信协议。

传输前,采用“三次握手”方式建立连接,所以是可靠的。

在连接中可进行大数据量的传输。

连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低。

UDP协议特点

UDP是一种无连接、不可靠传输的协议。

将数据源IP、目的地IP和端口封装成数据包,不需要建立连接每个数据包的大小限制在64KB内

发送不管对方是否准备好,接收方收到也不确认,故是不可靠的

可以广播发送,发送数据结束时无需释放资源,开销小,速度快。

IP常用命令:

ipconfig:查看本机IP地址

ping IP地址:检查网络是否连通

特殊lP地址:

本机IP:127.0.0.1或者localhost:称为回送地址也可称本地回环地址,只会寻找当前所在本机。

 

UDP通信-快速入门

构造器

说明

public DatagramPacket(byte[] buf, int length,InetAddress address,int port)

创建发送端数据包对象

buf:要发送的内容,字节数组

length:要发送内容的字节长度

address:接收端的IP地址对象

port:接收端的端口号

public DatagramPacket( byte[] buf, int length)

创建接收端的数据包对象

buf:用来存储接收的内容

length:能够接收内容的长度

构造器

说明

public DatagramSocket()

创建发送端的Socket对象,系统会随机分配一个端口号。

public DatagramSocket(int port)

创建接收端的Socket对象并指定端口号

使用UDP实现一发一收

/**
 * 接收端
 */
public class ServerDemo1 {
	public static void main(String[] args) throws Exception {
		System.out.println("================服务端启动=====================");
		// 1.创建接收端对象,注册端口
		DatagramSocket socket = new DatagramSocket(8888);

		// 2.创建数据包对象接收对象
		byte[] buffer = new byte[1024 * 64];
		DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

		// 3.等待接受数据即可
		socket.receive(packet);

		// 4.取出数据
		int len = packet.getLength();
		String str = new String(buffer, 0, len);
		System.out.println("亲爱的:" + str);
  
   		//获取发送端的IP和端口
		String ip = packet.getAddress().toString();
		System.out.println(ip);
		int port = packet.getPort();
		System.out.println(port);
  	

                socket.close();
	}
}
/**
 * 发送端
 */
public class ClientDemo1  {
	public static void main(String[] args) throws Exception {
		System.out.println("================客户端启动=====================");
		//1.创建发送端对象
		DatagramSocket socket = new DatagramSocket();
		//2.创建一个数据包对象封装数据
		/**
		 * 参数一:封装要发送的数据
		 * 参数二:要发送数据的长度(length)
		 * 参数三:服务端的IP地址
		 * 参数四:服务端的端口
		 */
		byte[] buffer = "我喜欢你,可以做我女朋友吗?".getBytes();
		DatagramPacket packet = new DatagramPacket(buffer, buffer.length,InetAddress.getLocalHost(),8888);
		//3.将数据发送出去
		socket.send(packet);
		
		socket.close();
	}	
}

使用UDP实现多发多收

/**
 * 服务端
 */
public class ServerDemo2 {
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("================服务端启动=====================");
		// 1.创建接收端对象,注册端口
		DatagramSocket socket = new DatagramSocket(8888);
		// 2.创建数据包对象接收对象
		byte[] buffer = new byte[1024 * 64];
		DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
		while (true) {
			// 3.等待接受数据即可
			socket.receive(packet);
			// 4.取出数据
			int len = packet.getLength();
			String str = new String(buffer, 0, len);
			if("exit".equals(str)) {
				System.out.println("对方已离线");
				socket.close();
				break;
			}
			System.out.println("亲爱的:" + str);
		}	
	}

}
/**
 * 客户端
 */
public class ClientDemo2 {

	public static void main(String[] args) throws Exception {
		System.out.println("================客户端启动=====================");
		//1.创建发送端对象
		DatagramSocket socket = new DatagramSocket();
		//2.创建一个数据包对象封装数据
		/**
		 * 参数一:封装要发送的数据
		 * 参数二:要发送数据的长度(length)
		 * 参数三:服务端的IP地址
		 * 参数四:服务端的端口
		 */
		Scanner s = new Scanner(System.in);
		while (true) {
			byte[] buffer = s.nextLine().getBytes();
			DatagramPacket packet = new DatagramPacket(buffer, buffer.length,InetAddress.getLocalHost(),8888);
			//3.将数据发送出去
			socket.send(packet);
			if("exit".equals(buffer)) {
				socket.close();
				break;
			}
		}
	}
}

TCP通信-快速入门

TCP是一种面向连接,安全、可靠的传输数据的协议

传输前,采用“三次握手”方式,是可靠的

在连接中可进行大数据量的传输

注意:在java中只要是使用java.net.Socket类实现通信,底层即是使用了TCP协议

TCP实现一发一收

public class ClientDemo_TCP {
	/**
	 	完成Socket网络编程,实现一发一收 
	 	客户端
	 */
	public static void main(String[] args) {
		try {
			// 1.创建Socket通信管道请求有服务端的连接
			// public Socket(String host , int port)
			// 参数一:服务端的IP地址
			// 参数二:服务端的端口号
			Socket socket = new Socket("127.0.0.1", 7777);
			// 2.从Socket通信管道中获得字节输出流,负责发送数据
			OutputStream os = socket.getOutputStream();
			// 3.把低级的输出流包装成打印流
			PrintStream ps = new PrintStream(os);
			// 4.发送信息
			ps.println("你好!");
			ps.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
public class ServerDemo_TCP {
	/**
	 * 服务端
	 */
	public static void main(String[] args) {
		try {
			// 1.注册端口
			ServerSocket serverSocket = new ServerSocket(7777);
			// 2.必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
			Socket socket = serverSocket.accept();
			// 3.把字节输入流包装成缓冲字符输入流进行消息的接收
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			//4.通过按行读取消息
			String msg;
			if ((msg = br.readLine()) != null) {
				System.out.println(socket.getRemoteSocketAddress()+"的用户向您发出"+msg);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

TCP通信-多发多收消息

public class ClientDemo_TCP {
	/**
	 * 完成Socket网络编程,实现多发多收 客户端
	 */
	public static void main(String[] args) {
		try {
			System.out.println("=========客户端正在运行==========");
			// 1.创建Socket通信管道请求有服务端的连接
			// public Socket(String host , int port)
			// 参数一:服务端的IP地址
			// 参数二:服务端的端口号
			Socket socket = new Socket("127.0.0.1", 7777);
			// 2.从Socket通信管道中获得字节输出流,负责发送数据
			OutputStream os = socket.getOutputStream();
			// 3.把低级的输出流包装成打印流
			PrintStream ps = new PrintStream(os);
			// 4.发送信息
			Scanner s = new Scanner(System.in);
			while (true) {
				String msg = s.nextLine();
				if ("exit".equals(msg)) {
					socket.close();
					break;
				}
				ps.println(msg);
				ps.flush();

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
public class ServerDemo_TCP {
	/**
	 * 服务端
	 */
	public static void main(String[] args) {
		try {
			System.out.println("=========服务端正在运行==========");
			// 1.注册端口
			ServerSocket serverSocket = new ServerSocket(7777);
			// 2.必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
			Socket socket = serverSocket.accept();
			// 3.把字节输入流包装成缓冲字符输入流进行消息的接收
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			//4.通过按行读取消息
			String msg;
			while((msg = br.readLine()) != null) {
				System.out.println(socket.getRemoteSocketAddress()+"的用户向您发出"+msg);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

TCP通信-同时接受多个客户端消息

public class ClientDemo_TCP2 {

	public static void main(String[] args) {
		try {
			System.out.println("=========客户端正在运行==========");
			// 1.创建Socket通信管道请求有服务端的连接
			// public Socket(String host , int port)
			// 参数一:服务端的IP地址
			// 参数二:服务端的端口号
			Socket socket = new Socket("127.0.0.1", 7777);
			// 2.从Socket通信管道中获得字节输出流,负责发送数据
			OutputStream os = socket.getOutputStream();
			// 3.把低级的输出流包装成打印流
			PrintStream ps = new PrintStream(os);
			// 4.发送信息
			Scanner s = new Scanner(System.in);
			while (true) {
				String msg = s.nextLine();
				if ("exit".equals(msg)) {
					socket.close();
					break;
				}
				ps.println(msg);
				ps.flush();

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
public class ServerDemo_TCP2 {

	public static void main(String[] args) {

		System.out.println("=========服务端正在运行==========");
		try {
			// 1.注册端口
			ServerSocket serverSocket = new ServerSocket(7777);
			while (true) {
				// 2.必须调用accept方法:等待接收客户端的Socket连接请求,建立Socket通信管道
				Socket socket = serverSocket.accept();
				//每接收到一个,就创建一个新的线程
				new ServerReaderThreadDemo(socket).start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
public class ServerReaderThreadDemo extends Thread {
	private Socket socket;

	public ServerReaderThreadDemo(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		try {
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String msg;
			while ((msg = br.readLine()) != null) {
				System.out.println(socket.getRemoteSocketAddress() + "发出:" + msg);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

TCP通信-使用线程池优化

/**
 	客户端
 */
public class ClientDemo3 {

	public static void main(String[] args) {
		try {
			System.out.println("=========客户端正在运行==========");
			// 1.创建Socket通信管道请求有服务端的连接
			// public Socket(String host , int port)
			// 参数一:服务端的IP地址
			// 参数二:服务端的端口号
			Socket socket = new Socket("127.0.0.1", 6666);
			// 2.从Socket通信管道中获得字节输出流,负责发送数据
			OutputStream os = socket.getOutputStream();
			// 3.把低级的输出流包装成打印流
			PrintStream ps = new PrintStream(os);
			// 4.发送信息
			Scanner s = new Scanner(System.in);
			while (true) {
				String msg = s.nextLine();
				ps.println(msg);
				ps.flush();

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
/**
	服务端
 */
public class ServerDemo3 {
	private static ExecutorService serverPool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,
			new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

	public static void main(String[] args) {
		System.out.println("=========服务端正在运行==========");
		try {
			ServerSocket serverSocket = new ServerSocket(6666);
			Socket socket = serverSocket.accept();
			System.out.println(socket.getRemoteSocketAddress()+"上线了");
			Runnable target = new ServerReaderRunnable(socket);
			serverPool.execute(target);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
public class ServerReaderRunnable implements Runnable {

	private Socket socket;

	public ServerReaderRunnable(Socket socket) {
			this.socket = socket;
	}

	@Override
	public void run() {
		try {
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String msg;
			while ((msg = br.readLine()) != null) {
				System.out.println(socket.getRemoteSocketAddress() + "发出:" + msg);
			}

		} catch (Exception e) {
			System.out.println(socket.getRemoteSocketAddress()+"下线了");
			
		}

	}

}

TCP实战案例——即时通信

/**
 	客户端
 */
public class ClientDemo3 {
	public static void main(String[] args) {
		try {
			System.out.println("=========客户端正在运行==========");
			// 1.创建Socket通信管道请求有服务端的连接
			// public Socket(String host , int port)
			// 参数一:服务端的IP地址
			// 参数二:服务端的端口号
			Socket socket = new Socket("127.0.0.1", 6666);
			new ClientReaderThread(socket).start();
			// 2.从Socket通信管道中获得字节输出流,负责发送数据
			OutputStream os = socket.getOutputStream();
			// 3.把低级的输出流包装成打印流
			PrintStream ps = new PrintStream(os);
			// 4.发送信息
			Scanner s = new Scanner(System.in);
			while (true) {
				String msg = s.nextLine();
				ps.println(msg);
				ps.flush();

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
class ClientReaderThread extends Thread{
	private Socket socket;
	
	public ClientReaderThread(Socket socket) {
		this.socket = socket;
	}
	public void run() {
		try {
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String msg;
			while ((msg = br.readLine()) != null) {
				System.out.println(socket.getRemoteSocketAddress() + "发出:" + msg);
			}

		} catch (Exception e) {
			System.out.println(socket.getRemoteSocketAddress()+"下线了");
			
		}
  
    }
	
	
}
/**
	服务端
 */
public class ServerDemo3 {
	public static ArrayList<Socket> ReaderAll = new ArrayList<>();
	private static ExecutorService serverPool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,
			new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

	public static void main(String[] args) {
		System.out.println("=========服务端正在运行==========");
		try {
			ServerSocket serverSocket = new ServerSocket(6666);
			while (true) {
				Socket socket = serverSocket.accept();
				ReaderAll.add(socket);
				System.out.println(socket.getRemoteSocketAddress()+"上线了");
				Runnable target = new ServerReaderRunnable(socket);
				serverPool.execute(target);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}
public class ServerReaderRunnable implements Runnable{

	private Socket socket;

	public ServerReaderRunnable(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		try {
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String msg;
			while ((msg = br.readLine()) != null) {
				System.out.println(socket.getRemoteSocketAddress() + "发出:" + msg);
				sendMagToAll(msg);

			}

		} catch (Exception e) {
			System.out.println(socket.getRemoteSocketAddress() + "下线了");
			ServerDemo3.ReaderAll.remove(socket);

		}

	}

	private void sendMagToAll(String msg) throws Exception {
		for (Socket socket : ServerDemo3.ReaderAll) {
			PrintStream ps = new PrintStream(socket.getOutputStream());
			ps.println(msg);
			ps.flush();

		}

	}
}

这是本人的的见解,如有错误或不足希望各位大佬们给予指正和补充

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值