一、InetAddress类和Socket
1.InetAddress类
相关方法
方法名 | 功能 |
---|---|
getLocalHost | 获取本机InetAddress对象 |
getByName | 根据指定主机名/域名获取ip地址对象 |
getHostName | 获取InetAddress对象的主机名 |
getHostAddress | 获取InetAddress对象的地址 |
快速入门
import java.net.InetAddress;
import java.net.UnknownHostException;
public class test {
public static void main(String[] args) throws UnknownHostException {
//获取本机 InetAddress 对象 getLocalHost
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
//根据指定主机名/域名获取 ip 地址对象 getByName
InetAddress byName = InetAddress.getByName("DESKTOP-RT31TG6");
System.out.println(byName);
InetAddress byName1 = InetAddress.getByName("www.baidu.com");
System.out.println(byName1);
//获取 byName1 对象的主机名 getHostName
String hostName = byName1.getHostName();
System.out.println(hostName);
//获取 byName1 对象的地址 getHostAddress
String hostAddress = byName1.getHostAddress();
System.out.println(hostAddress);
}
}
2.Socket
基本介绍
Socket开发网络应用程序被广泛采用,以至于称为事实的标准。
- 通信的两端都要有Socket,是两台机器通信的端点
- 网络通信其实就是Socket间的通信
- Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO流进行传输的
- 一般主动发起通信的应用程序属于客户端,等待通信请求的为服务端
二、TCP网络通信编程
1.基本介绍
- 基于客户端—服务端的网络通信
- 底层使用的是TCP/IP协议
- 应用场景举例:客户端发送数据,服务端接受并显示控制台
- 基于Socket的TCP编程
注意:需先启动服务端,然后再启动客户端
2.应用案例
案例一
要求:
- 使用字节流
- 编写一个服务器端和客户端
- 服务器端在9999端口监听
- 客户端连接到服务器端,发送“hello server”,然后退出
- 服务器端接收到客户端发送的信息,输出,并退出
服务器Server端
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//服务端
public class SocketTCPServer {
public static void main(String[] args) throws IOException {
//在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
ServerSocket serverSocket= new ServerSocket(9999);
System.out.println("服务端对9999进行端口监听,等待连接..");
//等待连接
//细节:serverSocket可以通过accept()返回多个Socket,多个客户端连接服务器的并发
Socket socket = serverSocket.accept();
System.out.println("服务端 socket =" + socket.getClass());
//通过 socket.getInputStream() 读取客户端写入到数据通道的数据
InputStream inputStream = socket.getInputStream();
//再通过IO流进行读取
byte[] bytes = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(bytes)) != -1){
System.out.println(new String(bytes,0,readLen));
}
//关闭流和socket,必须关闭
inputStream.close();
socket.close();
serverSocket.close();
}
}
客户端Client
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//客户端
public class SocketTCPClient {
public static void main(String[] args) throws IOException {
//连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 socket返回为:"+socket.getClass());
//通过socket.getOutputStream()获取socket 对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//通过IO流,写入数据到数据通道
outputStream.write("hello server".getBytes());
//关闭流对象和 socket,必须关闭
outputStream.close();
socket.close();
System.out.println("客户端退出....");
}
}
案例二
要求:
- 使用字节流
- 编写一个服务器端和客户端
- 服务器端在9999端口监听
- 客户端连接到服务器端,发送“hello server”,并接收服务器端回发的 “hello client” 然后再退出
- 服务器端接收到客户端发送的信息,输出,并发送“hello client”给客户端,最后再退出
注意:当流写入数据通道后,需要设置结束标记
服务器Server端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//服务端
public class SocketTCPServer {
public static void main(String[] args) throws IOException {
//在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
ServerSocket serverSocket= new ServerSocket(9999);
System.out.println("服务端对9999进行端口监听,等待连接..");
//等待连接
//细节:serverSocket可以通过accept()返回多个Socket,多个客户端连接服务器的并发
Socket socket = serverSocket.accept();
System.out.println("服务端 socket =" + socket.getClass());
//通过 socket.getInputStream() 读取客户端写入到数据通道的数据
InputStream inputStream = socket.getInputStream();
//再通过IO流进行读取
byte[] bytes = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(bytes)) != -1){
System.out.println(new String(bytes,0,readLen));
}
//获取socket相关联的输出流,写入数据到数据通道,使用字节流
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello client".getBytes());
//设置结束标记
socket.shutdownOutput();
//关闭流和socket,必须关闭
outputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
客户端Client
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//客户端
public class SocketTCPClient {
public static void main(String[] args) throws IOException {
//连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 socket返回为:"+socket.getClass());
//通过socket.getOutputStream()获取socket 对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//通过IO流,写入数据到数据通道
outputStream.write("hello server".getBytes());
//设置结束标记
socket.shutdownOutput();
//获取socket相关联的输入流,读取数据并显示。使用的字节流
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(bytes)) != -1){
System.out.println(new String(bytes,0,readLen));
}
//关闭流对象和 socket,必须关闭
outputStream.close();
socket.close();
System.out.println("客户端退出....");
}
}
案例三
要求:
- 使用字符流
- 编写一个服务器端和客户端
- 服务器端在9999端口监听
- 客户端连接到服务器端,发送“hello server”,并接收服务器端回发的 “hello client” 然后再退出
- 服务器端接收到客户端发送的信息,输出,并发送“hello client”给客户端,最后再退出
将字节流转换为字符流,需要用到转换流
注意:这里设置结束标记除了使用socket.shutdownOutput();也可以用 如:writer.newLine()设置结束标记,而且对面接收数据需要使用readLine来接收
服务器Server端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//服务端
public class SocketTCPServer {
public static void main(String[] args) throws IOException {
//在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
ServerSocket serverSocket= new ServerSocket(9999);
System.out.println("服务端对9999进行端口监听,等待连接..");
//等待连接
//细节:serverSocket可以通过accept()返回多个Socket,多个客户端连接服务器的并发
Socket socket = serverSocket.accept();
System.out.println("服务端 socket =" + socket.getClass());
//通过 socket.getInputStream() 读取客户端写入到数据通道的数据
InputStream inputStream = socket.getInputStream();
//再通过IO流进行读取,使用字符流读取
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//获取socket相关联的输出流,写入数据到数据通道
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello client");
bufferedWriter.newLine(); //插入一个换行符,表示写入的内容结束,但是要求对面使用readLine()进行读取
bufferedWriter.flush(); //如果使用字符流,则需要手动刷新,否则不会写数据通道
//关闭流和socket,必须关闭,这里只需要关闭外层流即可,按照先打开后关闭的原则
bufferedWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();
}
}
客户端Client
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//客户端
public class SocketTCPClient {
public static void main(String[] args) throws IOException {
//连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 socket返回为:"+socket.getClass());
//通过socket.getOutputStream()获取socket 对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//通过IO流,写入数据到数据通道,这里使用字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello server");
bufferedWriter.newLine(); //插入一个换行符,表示写入的内容结束,但是要求对面使用readLine()进行读取
bufferedWriter.flush(); //如果使用字符流,则需要手动刷新,否则不会写数据通道
//获取socket相关联的输入流,读取数据并显示。
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//关闭流对象和 socket,必须关闭,这里只需要关闭外层流即可,按照先打开后关闭的原则
bufferedReader.close();
bufferedWriter.close();
socket.close();
System.out.println("客户端退出....");
}
}
2.网络上传文件
案例四
要求:
- 编写一个服务器端和客户端
- 服务器端在9999端口监听
- 客户端连接服务端,发送一张图片 F:\\java.jpeg
- 服务器端接收到客户端发送的图片,保存到src下,发送“收到图片”,然后再退出
- 客户端接收到服务端发送的“收到图片”,再退出
- 需使用一个工具类StreamUtils.java
StreamUtils工具类
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* 此类用于演示关于流的读写方法
*
*/
public class StreamUtils {
/**
* 功能:将输入流转换成byte[], 即可以把文件的内容读入到byte[]
* @param is
* @return
* @throws Exception
*/
public static byte[] streamToByteArray(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
byte[] b = new byte[1024];//字节数组
int len;
while((len=is.read(b))!=-1){//循环读取
bos.write(b, 0, len);//把读取到的数据,写入bos
}
byte[] array = bos.toByteArray();//然后将bos 转成字节数组
bos.close();
return array;
}
/**
* 功能:将InputStream转换成String
* @param is
* @return
* @throws Exception
*/
public static String streamToString(InputStream is) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder= new StringBuilder();
String line;
while((line=reader.readLine())!=null){
builder.append(line+"\r\n");
}
return builder.toString();
}
}
服务器Server端
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//服务端
public class SocketTCPServer {
public static void main(String[] args) throws Exception {
//在本机9999端口进行监听,(在本机的9999端口没有被占用的情况下)
ServerSocket serverSocket= new ServerSocket(9999);
System.out.println("服务端对9999进行端口监听,等待连接..");
//等待连接
Socket socket = serverSocket.accept();
//读取客户端发送的数据
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//读取管道传过来的文件字节数组
byte[] bytes = StreamUtils.streamToByteArray(bis);
//将得到的字节数组,写入到指定的路径,得到一个文件
String newFilePath = "src\\java.jpeg";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFilePath));
bos.write(bytes);
//向客户端回复信息,字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("收到图片!");
bufferedWriter.newLine();
bufferedWriter.flush();
//关闭资源
bufferedWriter.close();
bos.close();
bis.close();
socket.close();
serverSocket.close();
}
}
客户端Client
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author wangbo
* @version 1.0
*/
//客户端
public class SocketTCPClient {
public static void main(String[] args) throws Exception {
//连接本机的 9999 端口, 如果连接成功,则返回 Socket 对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
String filepath = "F://java.jpeg";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filepath));
//把读取的内容转换成字节数组,使用工具类
byte[] bytes = StreamUtils.streamToByteArray(bis);
//通过socket获取输出流,将bytes数据发送给服务器
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes); //将文件写入数据通道
socket.shutdownOutput();
//接收信息
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
bufferedReader.close();
bos.close();
bis.close();
socket.close();
}
}