第十六章 网络编程
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() + ":\n" + 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() + ":\n" + 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();
}
}
}
}
}
您的资助是我最大的动力!
金额随意,欢迎来赏!