网络编程
约 2412 字大约 8 分钟
2026-04-04
软件架构
B/S:Brower/Server结构,指的是浏览器和服务器结构
C/S:Client/Server结构,指的是客户端和服务器结构

IP地址:互联网协议地址,ip地址是给网络中的计算机设备做唯一的编号
IPV4:是一个32为二进制数,通常是四个字节,表现形式a.b.c.d每一个单词的取值范围0-255之间,总的范围为42亿个
IPV6:为了扩大地址空间,决定采用IPV6重新定义地址空间,采用128位地址长度16个字节,分成8组16进制数ABCD:EF01:2345:6789:ABCD:EF01:2345:6789可以为地球上的每一-粒沙子定义地址 本机ip地址特殊写法: 127.0.0.1 localhost
端口号 :就是设备中进程的唯一标识。采用两个字节标识的整数,它的取值范围0-65535
其中0-1023这些端口已经被征用了,常规的都是1024往后定义
同一台机器不能出现两个相同端口号的程序

网络通信协议
计算机通信必须要遵守的协议,协议中规定了数据的传输格式,传输速率,传输步骤;双方必须同时遵守,才能进行数据交换
TCP/IP
是互联网中最广泛的协议,它定义了计算机如何连入互联网,以及数据如何在它们之间进行传输的标准。
面向连接的协议 。在传输数据之前,在发送端和接收端建立逻辑联系,再传输数据,提供了两台计算机之间可靠无差错的数据传输。
日常使用:浏览器,下载
三次握手

UDP
用户数据报协议,是一个面向无连接的协议 。 传输数据时不需要建立连接,不管对方服务是否启动,直接将数据、数据源和目的地都封装到数据包中,直接发送 传输速度快,容易丢包。 常用于视频会议
Socket
public class Socket extends Object implements Closeable 该类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通信的端点。 其中还包含IP地址和端口号的网络单位
构造方法
public Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。 host:服务器的IP地址port:服务器的端口号 如果指定的主机是null ,则相当于将地址指定为InetAddress.getByName(null) 。 换句话说,它等同于指定环回接口的地址。
成员方法
public OutputStream getOutputStream() 返回此套接字的输出流。 public InputStream getInputStream() 返回此套接字的输入流。 public void close() 关闭此套接字。
实现步骤
创建一个
客户端对象Socket,构造方法中绑定服务器的IP地址 和端口号使用Socket对象中的
getOutputStream获取网络字节输出流对象OutputStream使用OutputStream对象的
write()方法,将给服务器数据发送使用Socket对象的
getInputStream,获取网络字节输入流对象InputStream使用InputStream的
read()方法,读取服务器发回的数据关闭流,释放资源
package com.ntework.demo1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* @Description tcp通信的客户端,向服务器发送连接请求
* @Classname Client
* @Date 2021/8/18 10:42
* @Created by 折腾的小飞
*/
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 2000);
OutputStream os = socket.getOutputStream();
os.write("客户端发送".getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
while ((len=is.read(bytes))!=-1){
System.out.println(new String(bytes, 0, len));
}
socket.close();
}
}ServerSocket
public class ServerSocket extends Object implements Closeable 该类实现服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行某些操作,然后可能将结果返回给请求者。
构造方法
public ServerSocket(int port) 创建绑定到指定端口的服务器套接字。 端口号0表示端口号自动分配,通常来自临时端口范围。 然后可以通过调用getLocalPort来检索此端口号。 传入连接指示(连接请求)的最大队列长度设置为50 。 如果队列已满时连接指示到达,则拒绝连接。
成员方法
public Socket accept() 侦听对此套接字的连接并接受它。
实现步骤
创建服务器套接字对象和系统要指定的端口号
使用accept()方法,获取到请求的客户端对象Socket
使用流对象...
package com.ntework.demo1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Description 服务器端,接收客户端发来的连接请求,给客户端返回数据
* @Classname Server
* @Date 2021/8/18 10:44
* @Created by 折腾的小飞
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(2000);
Socket socket = ss.accept();
System.out.println("获得客户端的连接,监听端口"+socket.getLocalPort());
InputStream is = socket.getInputStream();
byte[] bytes=new byte[1024];
int len=is.read(bytes);
System.out.println(new String(bytes, 0, len));
OutputStream os = socket.getOutputStream();
os.write("我已接收到了你的信息,感谢!".getBytes());
socket.close();
ss.close();
}
}文件的上传和下载
shutdownOutput
void shutdownOutput():禁用文件的输出流
客户端上传

package com.network.demo2;
import java.io.*;
import java.net.Socket;
/**
* @Description 上传客户端
* @Classname UpLoadClient
* @Date 2021/8/18 13:44
* @Created by 折腾的小飞
*/
public class UploadClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 3000);
OutputStream os = socket.getOutputStream();
FileInputStream fis = new FileInputStream(new File("C:\\Users\\折腾的小飞\\Desktop\\图片\\code\\java.png"));
int len;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes)) != -1) {
os.write(bytes, 0, len);
}
//结束标识
// void shutdownOutput():禁用文件的输出流
socket.shutdownOutput();
InputStream is = socket.getInputStream();
while ((len = is.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
socket.close();
}
}服务端下载

package com.network.demo2;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Description 上传服务端
* @Classname UploadServer
* @Date 2021/8/18 13:44
* @Created by 折腾的小飞
*/
public class UploadServer {
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(3000);
Socket socket=ss.accept();
FileOutputStream fos=new FileOutputStream(new File("java.png"));
InputStream is=socket.getInputStream();
int len;
byte[] bytes=new byte[1024];
while ((len=is.read(bytes))!=-1){
fos.write(bytes,0,len);
}
socket.shutdownInput();
OutputStream os=socket.getOutputStream();
os.write("已接收文件!".getBytes());
ss.close();
socket.close();
}
}Client,Server
package com.network.Work8_18;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Description 服务器,接收客户端的信息,并存储文件或者发送要下载图片的信息
* @Classname Server
* @Date 2021/8/18 20:31
* @Created by 折腾的小飞
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(6000);
System.out.println("等待连接。。。");
Socket socket = ss.accept();
System.out.println("开始监听端口:" + ss.getLocalPort());
// 创建文件,接收来自客户端的信息,存储到磁盘文件中
InputStream is = socket.getInputStream();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("img\\java.png"));
int len;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes)) != -1) {
bos.write(bytes, 0, len);
bos.flush();
}
System.out.println("完成接收客户端的信息,存储完成!");
bos.close();
// 读取磁盘文件,向客户端发送
OutputStream os = socket.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("img\\java.png"));
while ((len = bis.read(bytes)) != -1) {
os.write(bytes, 0, len);
}
// 发送完成信号
socket.shutdownInput();
System.out.println("返回客户端的请求下载图片的请求,发送完成!");
bis.close();
socket.close();
}
}
package com.network.Work8_18;
import java.io.*;
import java.net.Socket;
/**
* @Description 客户端,像服务器发送下载图片请求,接收来自服务器端的图片信息
* @Classname Client
* @Date 2021/8/18 20:31
* @Created by 折腾的小飞
*/
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 6000);
// 新建目录
File file=new File("img");
if (!file.exists()){
file.mkdir();
}
// 读取磁盘文件,向服务器发送
FileInputStream fis = new FileInputStream("java.png");
OutputStream os = socket.getOutputStream();
int len;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes)) != -1) {
os.write(bytes, 0, len);
}
// 发送传输完成信息
socket.shutdownOutput();
System.out.println("向服务器-传输完成!");
fis.close();
// 创建磁盘文件,接收来自服务器端的信息,存储到文件中
FileOutputStream fos=new FileOutputStream("java2.png");
InputStream is=socket.getInputStream();
while ((len=is.read(bytes))!=-1){
fos.write(bytes,0,len);
fos.flush();
}
System.out.println("从服务器-接收完成!");
fos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
单人聊天
OutputStreamWriter
public class OutputStreamWriter extends Writer
OutputStreamWriter是从字符流 到字节流 的桥接器:使用指定的charset写入其中的字符编码为字节。
构造方法
public OutputStreamWriter(OutputStream out, Charset cs) 创建使用给定charset的OutputStreamWriter。
Server
package com.network.demo4;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* @Description TODO
* @Classname Server
* @Date 2021/8/18 17:43
* @Created by 折腾的小飞
*/
public class Server {
private ServerSocket serverSocket;
public static void main(String[] args) {
try {
Server server=new Server();
server.work();
} catch (IOException e) {
e.printStackTrace();
}
}
public Server() throws IOException {
System.out.println("服务器初始化");
this.serverSocket=new ServerSocket(5000);
System.out.println("服务器初始化完成,等待客户端连接...");
}
public void work(){
try {
Socket socket=serverSocket.accept();
System.out.println("已接收到一个客户端连接");
ClientHandler clientHandler=new ClientHandler(socket);
Thread thread=new Thread(clientHandler);
thread.start();
InputStream is=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is,"UTF-8");
BufferedReader br=new BufferedReader(isr);
while (true){
String line = br.readLine();
System.out.println("客户端:"+line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
OutputStream os=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(os,"UTF-8");
PrintWriter pw=new PrintWriter(osw,true);
Scanner sc=new Scanner(System.in);
while (true){
String line = sc.nextLine();
pw.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}Client
package com.network.demo4;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
/**
* @Description TODO
* @Classname Client
* @Date 2021/8/18 17:43
* @Created by 折腾的小飞
*/
public class Client {
private Socket socket;
public static void main(String[] args) {
try {
Client client=new Client();
client.work();
} catch (IOException e) {
e.printStackTrace();
}
}
public Client() throws IOException {
System.out.println("开始建立连接");
this.socket=new Socket("localhost",5000);
System.out.println("连接已建立");
}
public void work(){
try {
ServerHandle serverHandle=new ServerHandle();
Thread thread=new Thread(serverHandle);
thread.start();
OutputStream os=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(os,"UTF-8");
PrintWriter pw=new PrintWriter(osw,true);
Scanner sc=new Scanner(System.in);
while (true){
String line = sc.nextLine();
pw.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class ServerHandle implements Runnable{
@Override
public void run() {
try {
InputStream is=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is,"UTF-8");
BufferedReader br=new BufferedReader(isr);
String msg;
while ((msg=br.readLine())!=null){
System.out.println("服务器:"+msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}