网络编程
基本概念
????计算机网络是通过传输介质、通信设施和网络通信协议,把分散在不同地点的计算机设备互连起来的,实现资源共享和数据传输的系统。网络编程就是编写程序使互联网的两个(或多个)设备(如计算机)之间进行数据传输。
百度百科:分类 | 分层 | IP | 端口 | 套接字 | TCP | UDP | URL | URI
InetAddress 类
InetAddress 类,表示IP地址。
常用方法
byte[] getAddress() :返回原始 IP 地址;static InetAddress getByName(String host) :在给定主机名的情况下确定主机的 IP 地址;String getHostAddress() :返回 IP 地址字符串;String getHostName() :获取此 IP 地址的主机名;static InetAddress getLocalHost() :返回本地主机。
InetSocketAddress 类
InetSocketAddress 类,实现 IP套接字地址(IP 地址 + 端口号)。
构造方法
InetSocketAddress(InetAddress addr, int port) :根据 IP 地址和端口号创建套接字地址;InetSocketAddress(int port) :创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值;InetSocketAddress(String hostname, int port) :根据主机名和端口号创建套接字地址。
常用方法
InetAddress getAddress() :获取 InetAddress;String getHostName() :获取 hostname;int getPort() :获取端口号。
TCP网络编程
Socket 类
Socket 类,实现客户端套接字,套接字指的是两台设备之间通讯的端点。
构造方法
public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。
常用方法
public InputStream getInputStream() : 返回此套接字的输入流;public OutputStream getOutputStream() : 返回此套接字的输出流;public void close() :关闭此套接字;public void shutdownOutput() : 禁用此套接字的输出流。
ServerSocket 类
ServerSocket 类,实现了服务器套接字,该对象等待通过网络的请求。
构造方法
public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。
常用方法
public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞 直到建立连接。
代码实现
示例1
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;
@Slf4j
public class TCPDomo {
private static final String HOST = "127.0.0.1";
private static final Integer PORT = 8080;
@Test
public void server() {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
ByteArrayOutputStream outputStream = null;
try {
serverSocket = new ServerSocket(PORT);
socket = serverSocket.accept();
inputStream = socket.getInputStream();
outputStream = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
log.info("收到了来自于客户端 [{}] 的消息:{}", socket.getInetAddress().getHostName(), outputStream.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void client() {
Socket socket = null;
OutputStream os = null;
try {
InetAddress inet = InetAddress.getByName(HOST);
socket = new Socket(inet, PORT);
os = socket.getOutputStream();
os.write("你好,我是客户端!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
示例2
- 客户端向服务端发送消息;
- 服务端发向客户端回复消息;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
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;
@Slf4j
public class TCPDomo {
private static final String HOST = "127.0.0.1";
private static final Integer PORT = 8080;
@Test
public void server() {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
OutputStream outputStream = null;
try {
serverSocket = new ServerSocket(PORT);
socket = serverSocket.accept();
inputStream = socket.getInputStream();
byteArrayOutputStream = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
log.info("收到了来自于客户端 [{}] 的消息:{}", socket.getInetAddress().getHostName(), byteArrayOutputStream.toString());
outputStream = socket.getOutputStream();
outputStream.write("你好,我是服务端".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (byteArrayOutputStream != null) {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void client() {
Socket socket = null;
OutputStream outputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
InputStream inputStream = null;
try {
InetAddress inet = InetAddress.getByName(HOST);
socket = new Socket(inet, PORT);
outputStream = socket.getOutputStream();
outputStream.write("你好,我是客户端!".getBytes());
socket.shutdownOutput();
inputStream = socket.getInputStream();
byteArrayOutputStream = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
log.info("收到了来自服务端的消息:{}", byteArrayOutputStream.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (byteArrayOutputStream != null) {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
示例3
- 上传文件:客户端发送文件给服务端,服务端将文件保存在本地
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
@Slf4j
public class TCPDomo {
private static final String HOST = "127.0.0.1";
private static final Integer PORT = 8080;
@Test
public void server() {
ServerSocket serverSocket = null;
Socket socket = null;
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
try {
serverSocket = new ServerSocket(PORT);
socket = serverSocket.accept();
fileOutputStream = new FileOutputStream("image.jpg");
inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void client() {
Socket socket = null;
FileInputStream fileInputStream = null;
OutputStream outputStream = null;
try {
InetAddress inet = InetAddress.getByName(HOST);
socket = new Socket(inet, PORT);
fileInputStream = new FileInputStream("D:/image.jpg");
outputStream = socket.getOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
UDP网络编程
对于UDP来说,严格意义上,并没有所谓的Server和Client。
java.net 包给我们提供了两个类DatagramSocket (用于发送和接收数据报的套接字)和DatagramPacket (数据报的数据包。 )
DatagramSocket
构造方法
protected DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口; protected DatagramSocket(int port) 构造数据报套接字并将其绑定到本地主机上的指定端口; protected DatagramSocket(int port, InetAddress laddr) 创建一个数据报套接字,绑定到指定的本地地址。
DatagramPacket
构造方法
DatagramPacket(byte[] buf, int offset, int length) 构造一个 DatagramPacket用于接收指定长度的数据报包到缓冲区中; DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 构造用于发送指定长度的数据报包到指定主机的指定端口号上。
常用方法
byte[] getData() :返回数据报包中的数据; InetAddress getAddress() :返回该数据报发送或接收数据报的计算机的IP地址; int getLength() :返回要发送的数据的长度或接收到的数据的长度。
代码实现
示例1
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
@Slf4j
public class UDPDemo {
private static final String HOST = "127.0.0.1";
private static final Integer PORT = 8080;
@Test
public void receive() throws IOException {
DatagramSocket socket = new DatagramSocket(PORT);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
String msg = new String(packet.getData(), 0, packet.getLength());
log.info("接收到消息:[{}]", msg);
socket.close();
}
@Test
public void send() throws IOException {
DatagramSocket socket = new DatagramSocket();
InetAddress inet = InetAddress.getByName(HOST);
String msg = "你好,很高兴认识你!";
byte[] buffer = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length, inet, PORT);
socket.send(packet);
socket.close();
}
}
示例2
完成在线咨询功能,学生和老师在线一对一交流(多线程)。
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
@Slf4j
public class UDPDemo {
private static final String HOST = "127.0.0.1";
private static final Integer PORT_1 = 8080;
private static final Integer PORT_2 = 9090;
class Sender implements Runnable {
DatagramSocket socket = null;
BufferedReader bufferedReader = null;
private String toIP;
private int toPort;
public Sender(String toIP, int toPort) {
this.toIP = toIP;
this.toPort = toPort;
try {
socket = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
bufferedReader = new BufferedReader(new InputStreamReader(System.in));
}
@Override
public void run() {
while (true) {
try {
String msg = bufferedReader.readLine();
byte[] buffer = msg.getBytes();
InetAddress inet = InetAddress.getByName(toIP);
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length, inet, toPort);
socket.send(packet);
if (msg.equals("拜拜")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
socket.close();
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Receiver implements Runnable {
DatagramSocket socket = null;
private int fromPort;
private String msgFrom;
public Receiver(int fromPort, String msgFrom) {
this.fromPort = fromPort;
this.msgFrom = msgFrom;
try {
socket = new DatagramSocket(fromPort);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
byte[] buffer = new byte[1024 * 8];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
String msg = new String(packet.getData(), 0, packet.getLength());
log.info("{}:{}", msgFrom, msg);
if (msg.equals("拜拜")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
}
@Test
public void receive() {
new Thread(new Sender(HOST, PORT_1)).start();
new Thread(new Receiver(PORT_2, "学生")).start();
}
@Test
public void send() {
new Thread(new Sender(HOST, PORT_2)).start();
new Thread(new Receiver(PORT_1, "老师")).start();
}
}
URL 类
构造方法
URL(String spec) :根据 String 表示形式创建 URL 对象;URL(String protocol, String host, int port, String file) :根据指定协议名、主机名、端口号和文件名创建 URL 对象;URL(String protocol, String host, String file) :根据指定的协议名、主机名和文件名创建 URL。
常用方法
String getProtocol() :获取此 URL的协议名称;String getHost() :获取此 URL 的主机名;int getPort() :获取此 URL 的端口号;String getPath() :获取此 URL 的文件路径;String getFile() :获取此 URL 的文件名;String getQuery() :获取此 URL的查询部分;URLConnection openConnection() :返回一个URLConnection实例,表示与URL引用的远程对象的URL 。
- URLConnection类中有一个方法:
InputStream getInputStream() :返回从此打开的连接读取的输入流。
示例
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
@Slf4j
public class URLDemo {
@Test
public void visit() throws MalformedURLException {
URL url = new URL("https://www.baidu.com/");
log.info("获取协议名: {}", url.getProtocol());
log.info("获取主机名: {}", url.getHost());
log.info("获取端口号: {}", url.getPort());
log.info("获取文件路径: {}", url.getPath());
log.info("获取文件名: {}", url.getFile());
log.info("获取查询名: {}", url.getQuery());
}
@Test
public void download() throws IOException {
URL url = new URL("https://i0.hdslb.com/bfs/activity-plat/static/20190409/7d3fbe1b994526c1fae2b51bb7f2b633/S114GfcFE.png");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream is = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("bilibili.png");
byte[] buffer = new byte[1024];
int len=0;
while ((len=is.read(buffer))!=-1){
fos.write(buffer, 0, len);
}
urlConnection.disconnect();
is.close();
fos.close();
}
}
|