TCP网络编程
Socket
套接字(?)
应用案例1(字节流)
服务端
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author
* @date 2024-04-22 11:01
*/
public class SocketTCP01Server {
public static void main(String[] args) throws IOException {
//监听9999端口
//ServerSocket可通过accept()返回多个Socket[多个客户端连接高并发]
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端-端口9999等待连接...");
//没有客户端连接时,阻塞端口
//连接成功返回socket对象
Socket socket = serverSocket.accept();
System.out.println("socket is " + socket.getClass());
//通过输入流, 获取数据通道中写入的数据
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
//inputStream.read(buf) 方法尝试从输入流中读取数据到 buf 数组中。
// 它返回实际读取的字节数,如果已经到达流的末尾,则返回 -1。
while ((readLen = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0,readLen));
}
inputStream.close();
socket.close();
serverSocket.close();
System.out.println("服务端关闭...");
}
}
服务端控制台输出
服务端-端口9999等待连接...
socket is class java.net.Socket
hello, server
服务端关闭...
客户端
package socket;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @author
* @date 2024-04-22 11:09
* Client 发送"hello, server"
*/
public class SocketTCP01Client {
public static void main(String[] args) throws IOException {
//连接服务端(ip,port)
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("socket is " + socket.getClass());
//得到和socket对象得输出流对象
OutputStream outputStream = socket.getOutputStream();
//通过输出流,将数据写入数据通道
outputStream.write("hello, server".getBytes());
//关闭流和socket的对象,释放占用的资源
outputStream.close();
socket.close();
System.out.println("客户端关闭...");
}
}
客户端控制台输出
socket is class java.net.Socket
客户端关闭...
应用案例2(字节流)
需要设置结束标记
socket.shutdownOutput(); socket.shutdownInput();
服务端
package socket.example2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author
* @date 2024-04-22 14:04
*/
public class SocketTCP02Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端-端口9999等待连接...");
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf)) != -1) {
System.out.println(new String(buf, 0, readLen));
}
socket.shutdownInput();
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello, client".getBytes());
socket.shutdownOutput(); //设置写入结束标记
inputStream.close();
outputStream.close();
socket.close();
serverSocket.close();
}
}
控制台输出
服务端-端口9999等待连接...
hello, server
客户端
package socket.example2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @author
* @date 2024-04-22 14:04
*/
//@SuppressWarnings("all")
public class SocketTCP02Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
System.out.println("客户端socket已启动");
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello, server".getBytes());
socket.shutdownOutput(); //设置写入结束标记
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = inputStream.read(buf)) !=-1 ) {
System.out.println(new String(buf, 0, readLen));
}
socket.shutdownInput();
outputStream.close();
inputStream.close();
socket.close();
}
}
控制台输出
客户端socket已启动
hello, client
应用案例3(字符流)
服务端
package socket.example3;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author
* @date 2024-04-22 14:43
* 使用字符流
*/
public class SocketTCP03Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端-端口9999等待连接...");
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
//使用字符流,使用InputStreamReader 将inputStream字节流转成字符流
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream)
);
String str = bufferedReader.readLine();
System.out.println(str);
OutputStream outputStream = socket.getOutputStream();
//使用字符流写入数据通道
//OutputStreamWriter是从字符流到字节流的桥接
//1、字符的输出需要通过字符流来操作,但是本质最后还是通过字节流输出到计算机上进行存储的
//2、 因此OutputStreamWriter流的作用就是利用字节流作为底层输出流然后构建字符输出流,
// 字符输出流输出字符到流中,然后通过指定的字符集把流中的字符编码成字节输出到字节流中,
// 其作用就是一个桥梁,使得双方链接起来
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(outputStream)
);
bufferedWriter.write("hello, client 字符流");
bufferedWriter.newLine(); //插入一个换行符,表示写入的内容结束,要求对方使用readLine
bufferedWriter.flush(); //使用flush将缓冲区中的内容写入
bufferedWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();
}
}
控制台输出
服务端-端口9999等待连接...
hello, server 字符流
客户端
package socket.example3;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* @author
* @date 2024-04-22 14:43
* 使用字符流
*/
public class SocketTCP03Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
System.out.println("客户端socket已启动");
OutputStream outputStream = socket.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(outputStream)
);
bufferedWriter.write("hello, server 字符流");
bufferedWriter.newLine();
bufferedWriter.flush();
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream)
);
String str = bufferedReader.readLine();
System.out.println(str);
bufferedWriter.close();
bufferedReader.close();
socket.close();
}
}
控制台输出
客户端socket已启动
hello, client 字符流
应用案例4
服务端
package socket.example4;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author
* @date 2024-04-25 15:40
* 文件上传的服务端
*/
public class SocketTCP04FileUploadServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端-端口9999等待连接...");
Socket socket = serverSocket.accept();
//读取客户端发送的数据
BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
//获取当前的工作目录
String serverPath = System.setProperty("user.dir", "path/to/directory") + "\\0.jpeg";
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(serverPath));
bufferedOutputStream.write(bytes);
bufferedOutputStream.close();
//向客户端发送 收到图片的消息然后退出
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())
);
bufferedWriter.write("收到图片");
bufferedWriter.newLine();
bufferedWriter.flush();
socket.shutdownOutput();
bufferedWriter.close();
bufferedInputStream.close();
socket.close();
serverSocket.close();
}
}
控制台输出
服务端-端口9999等待连接...
客户端
package socket.example4;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author
* @date 2024-04-25 15:39
* 文件上传的客户端
*/
public class SocketTCP04FileUploadClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
System.out.println("客户端socket已启动");
String filePath = "E:\\0.jpeg";
//创建读取磁盘文件的输入流
BufferedInputStream bufferedInputStream = new BufferedInputStream(
new FileInputStream(filePath)
);
//bytes为filePath文件对应字节数组
byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
//通过socket获取到输出流,将bytes数据发送给服务器
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
socket.getOutputStream()
);
bufferedOutputStream.write(bytes); //将文件对应的字节数组的内容,写入到数据通道中
socket.shutdownOutput();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
String str = bufferedReader.readLine();
System.out.println("客户端接收到消息:" + str);
bufferedReader.close();
bufferedInputStream.close();
bufferedOutputStream.close();
socket.close();
}
}
控制台输出
客户端socket已启动
客户端接收到消息:收到图片
netstat指令
1.netstat -an 可以查看当前主机的网络情况,包括端口监听情况和网络连接情况
2.netstat -an | more 分页显示
3.netstat -anb 可以查看到哪个程序在监听
TCP连接
当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的。端口是不确定的是随机的
UDP网络编程
DatagramSocket和DatagramPacket
应用案例
A端
package UDPProgramming.example01;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* @author
* @date 2024-04-25 22:18
* UDP接收端
*/
public class UDPReceiverA {
public static void main(String[] args) throws IOException {
//创建一个datagramSocket对象在端口9999
DatagramSocket datagramSocket = new DatagramSocket(9999);
//构建datagramPacket对象用于接收数据
byte[] buffer = new byte[64 * 1024]; //UDP一个数据包最大64K
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
//通过网络传输的 datagramPacket 接收数据
System.out.println("等待接收数据中...");
datagramSocket.receive(datagramPacket); //没有接收到数据包会阻塞
//可以把 datagramPacket 进行拆包,取出里面的内容
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
System.out.println("A端收到消息--"+new String(data, 0, length));
byte[] sendData = "好的,明天见".getBytes();
datagramPacket = new DatagramPacket(sendData, sendData.length,
InetAddress.getByName("192.168.123.86"), 9998);
datagramSocket.send(datagramPacket);
System.out.println("发送完成");
//释放资源
datagramSocket.close();
System.out.println("A端关闭");
}
}
控制台输出
等待接收数据中...
A端收到消息--hello, 明天吃火锅~
发送完成
A端关闭
B端
package UDPProgramming.example01;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* @author
* @date 2024-04-25 22:19
* UDP发送端
*/
public class UDPReceiverB {
public static void main(String[] args) throws IOException {
DatagramSocket datagramSocket = new DatagramSocket(9998);
byte[] data = "hello, 明天吃火锅~".getBytes();
/*
* data -> 内容
* data.length -> 内容长度
* InetAddress.getByName("192.168.123.86") -> 主机地址
* 9999 -> 端口
*/
DatagramPacket datagramPacket = new DatagramPacket(
data,
data.length,
InetAddress.getByName("192.168.123.86"),
9999);
datagramSocket.send(datagramPacket);
System.out.println("发送完成");
datagramSocket.receive(datagramPacket);
int length = datagramPacket.getLength();
byte[] receiveData = datagramPacket.getData();
System.out.println("B端收到消息--" + new String(receiveData, 0, length));
//关闭资源
datagramSocket.close();
System.out.println("B端关闭");
}
}
控制台输出
发送完成
B端收到消息--好的,明天见
B端关闭