目录
IP
TCP/IP协议
数据的组织形式就是协议
netStat 指令 :查看网络状况
TCP和UDP协议
UDP(了解即可)
Socket
e.g TCP
服务器端代码(字节)
package e.gSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @auther xcz
* @data 2024/4/26
* @project e.gSocket
* 服务器端
*/
public class socketServer {
public static void main(String[] args) throws IOException {
//思路
//1、在本机的 9999 端口监听,等待连接
//细节 : 要求本机没有其他服务监听 9999 端口
//细节 : ServerSocket 可以通过 accept() 返回多个 Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务器端,在 9999 端口监听,等待连接~");
//2、当没有客户端连接 9999 端口时, 程序会 阻塞,等待连接
// 如果有客户端连接 则会返回 Socket 对象,程序继续执行
Socket socket = serverSocket.accept();
System.out.println("服务器端Socket =" + socket.getClass());
//3、通过 Socket.getInputStream() 读取
// 客户端写入数据通道中的数据,显示
InputStream inputStream = socket.getInputStream();
//4、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
inputStream.close();
socket.close();
serverSocket.close(); //关闭
outputStream.close();
}
}
客户端代码(字节 )
package e.gSocket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @auther xcz
* @data 2024/4/26
* @project e.gSocket
* 客户端 , 发送 “ hello,server” 给服务器端
*/
public class socketPC {
public static void main(String[] args) throws IOException {
//思路
//1、连接服务器(ip,端口)
//连接本机的 9999 端口, 如果链接成功,则会返回一个 Socket 对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 Socket = " + socket );
//2、连接上后,生成Socket 对象,通过socket.getOutputStream()得到和
//socket 对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,server".getBytes());
//设置 结束标记
socket.shutdownOutput();
//获取 socket 关联的输入流,读取数据(字节),并显示
//4、IO读取
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));//根据读取到的实际长度显示内容
}
//关闭流与相关资源,必须关闭
inputStream.close();
outputStream.close();
socket.close();
System.out.println("Socket与outputStream 已关闭,客户端退出!");
}
}
服务器端代码(字符)
package e.gSocket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @auther xcz
* @data 2024/4/26
* @project e.gSocket
* 使用字符流
*/
public class socketServer01 {
public static void main(String[] args) throws IOException {
//思路
//1、在本机的 9999 端口监听,等待连接
//细节 : 要求本机没有其他服务监听 9999 端口
//细节 : ServerSocket 可以通过 accept() 返回多个 Socket[多个客户端连接服务器的并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务器端,在 9999 端口监听,等待连接~");
//2、当没有客户端连接 9999 端口时, 程序会 阻塞,等待连接
// 如果有客户端连接 则会返回 Socket 对象,程序继续执行
Socket socket = serverSocket.accept();
System.out.println("服务器端Socket =" + socket.getClass());
//3、通过 Socket.getInputStream() 读取
// 客户端写入数据通道中的数据,显示
InputStream inputStream = socket.getInputStream();
//4、IO读取
//使用 转换流 InputStreamReader 将字节流转化会字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println("来自PC端内容:" + s);
//获取 socket 关联的输出流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("hello, client,i am king!");
bufferedWriter.newLine(); // 结束标记
bufferedWriter.flush(); //刷新
//关闭流与 socket
inputStream.close();
socket.close();
serverSocket.close(); //关闭
bufferedReader.close();
bufferedWriter.close();
}
}
客户端端代码(字符)
package e.gSocket;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* @auther xcz
* @data 2024/4/26
* @project e.gSocket
* 使用字符流
*/
public class socketPC01 {
public static void main(String[] args) throws IOException {
//思路
//1、连接服务器(ip,端口)
//连接本机的 9999 端口, 如果链接成功,则会返回一个 Socket 对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端 Socket = " + socket );
//2、连接上后,生成Socket 对象,使用字符流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("hello, server! 字符流");
//结束标记
bufferedWriter.newLine(); //插入换行,表示写入的内容结束,注意: 要求对方也必须用 readLine() 来读取!!
bufferedWriter.flush(); //使用字符流需要手动刷新,否则不会写入数据通道
//获取 socket 关联的输入流,读取数据(字节),并显示
//4、IO读取
//使用 转换流 InputStreamReader 将字节流转化会字符流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String s = bufferedReader.readLine();
System.out.println("来自服务器端内容:" + s);
//关闭流与相关资源,必须关闭
bufferedReader.close();
bufferedWriter.close();
socket.close();
System.out.println("Socket与outputStream 已关闭,客户端退出!");
}
}
UDP发送端
package eg.gUDP;
import java.io.IOException;
import java.net.*;
/**
* @auther xcz
* @data 2024/4/26
* @project eg.gUDP
* UDP 发送端
*/
public class uDPSender {
public static void main(String[] args) throws IOException {
// =====发送消息=====
// 创建一个 DatagramSocket 对象,准备在 9999 端口接收数据也可以发送数据
DatagramSocket datagramSocket = new DatagramSocket(9998);
//将要发送的数据 封装到一个 DatagramPacket 对象
byte[] data = "hello,明天出来嗨皮吗?".getBytes();
//说明:封装的对象 DatagramPacket (对象 data 内容字节数组 ,data.length, 主机IP, 端口)
DatagramPacket datagramPacket =
new DatagramPacket(data, data.length, InetAddress.getByName("192.168.128.1"),9999);
datagramSocket.send(datagramPacket);
//关闭资源
datagramSocket.close();
System.out.println("数据发送完毕!");
}
}
UDP接收端
package eg.gUDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* @auther xcz
* @data 2024/4/26
* @project eg.gUDP
* UDP接收端
*/
public class uDPReciver {
public static void main(String[] args) throws IOException {
// ==========接收消息============
// 创建一个 DatagramSocket 对象,准备在 9999 端口接收数据或发送数据
DatagramSocket datagramSocket = new DatagramSocket(9999);
// 构建一个 DatagramPacket 对象,准备接受数据
// UDP 协议中,一个数据包/报 最大64k
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);
//调用接收方法, 将通过网络传输的 DatagramPacket 对象
// 填充到 packet 对象
// 当有数据包 发送到 本机端口 9999 端口时,就会接收到数据到
// 如果没有数据包发送到 本机 9999 端口 ,就会阻塞等待
System.out.println("接收端 正在等待接收数据~");
datagramSocket.receive(datagramPacket);
//可以把 packet 进行拆包,取出数据,并显示
int length = datagramPacket.getLength(); //实际接收到的数据字节长度
byte[] data = datagramPacket.getData(); //接收到数据
String s = new String(data,0,length);
System.out.println(s);
// 关闭资源
datagramSocket.close();
System.out.println("数据接受完毕!");
}
}
服务器端发送音乐文件
package eg.downFile;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @auther xcz
* @data 2024/4/27
* @project eg.downFile
* 思路: 创建端口监听 -> 等待客户端连接 -> 收到客户端发送的文件名 -> 进行文件名判断 ->
* -> 构造文件路径读取本地文件 -> 转化为数组 -> 得到Socket关联输出流 -> 发送给客户端 -> 关闭流
* 服务器端
*/
public class server_ {
public static void main(String[] args) throws Exception {
// 在端口 9999 监听
System.out.println("服务器端,在 9999 端口监听");
ServerSocket serverSocket = new ServerSocket(9999);
// 等待客户端连接
Socket socket = serverSocket.accept();
// 读取客户端发送的文件名
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
String downLoad = new String(bytes,0,inputStream.read(bytes));
System.out.println("客户端希望下载的名称是:" + downLoad);
// 如果客户端希望下载的是稻香则读取 稻香,否则读取 不将就
String fielPath;
if ("稻香".equals(downLoad)){
fielPath = "e:\\音乐\\" + downLoad + ".mp3"; //"E:\音乐\稻香.mp3"
}else {
fielPath = "e:\\音乐\\不将就"+".mp3"; //"E:\音乐\不将就.mp3"
}
// 创建输入流 读取文件
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(fielPath));
// 用工具类读取文件,得到字符数组
byte[] data = streamToByteArray(bufferedInputStream);
// 将得到的字符数组 发送给 客户端 ,创建 Socket 关联的输出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
bufferedOutputStream.write(data);
socket.shutdownOutput(); //设置结束标记
//关闭流
socket.close();
inputStream.close();
bufferedOutputStream.close();
serverSocket.close();
System.out.println("文件发送完毕!服务端退出!");
}
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);
}
byte[] array = bos.toByteArray();
bos.close();
return array;
}
}
客户端接收音乐文件
package eg.downFile;
import com.sun.xml.internal.ws.util.StreamUtils;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
* @auther xcz
* @data 2024/4/27
* @project eg.downFile
* 思路:接收键盘输入 -> 连接服务器端发送文件名 -> 接收服务器端发的文件 -> 用工具类转换为字符数组
* -> 将数据写入到本地磁盘
* 客户端
*/
public class PC_ {
public static void main(String[] args) throws Exception {
//接收用户输入 下载文件名
Scanner scanner = new Scanner(System.in);
System.out.println("请输入想下载的歌曲:");
String fileName = scanner.next();
//连接服务端准备发送
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
//获取与 socket 关联的输出流
OutputStream outputStream = socket.getOutputStream();
outputStream.write(fileName.getBytes());
socket.shutdownOutput();
//接收 服务器端 发来的文件
BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
//使用工具类 来得到数据
byte[] data = streamToByteArray(bufferedInputStream);
//将文件下载到指定位置
String filePath = "e:\\" + fileName + ".mp3"; //"E:\音乐\稻香.mp3"
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath));
bufferedOutputStream.write(data);
//关闭相关资源
socket.close();
scanner.close();
outputStream.close();
bufferedOutputStream.close();
bufferedInputStream.close();
System.out.println("文件下载完毕!客户端退出!");
}
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);
}
byte[] array = bos.toByteArray();
bos.close();
return array;
}
}