网络编程
端口
-
端口表示不同计算机上的一个程序进程
-
不同的进程有不同的端口号 用来区分软件
-
被规定0~65535
-
TCP , UDP : 65536 *2 单个协议下,端口号不能冲突
-
端口分类:
- 公有端口: 1~1023
- HTTP: 80
- HTTPS: 443
- FTP : 21
- Telnet: 23
-
程序注册端口: 1014 ~49151 分配给用户和程序
- Tomcat: 8080
- MySQL : 3306
- Oracle:1521
-
动态 私有端口: 49152~65535
netstat -ano | findstr [port]
tasklist | find [port]
io流
Java的IO模型使用Decorator(装饰者)模式 按功能划分Stream 可以动态装配这些Stream 以便获得需要的功能
例如需要一个具有缓冲的文件输入流 则应当组合使用FileInputStream 和 BufferedInputStream
分类
-
按处理数据单位不同分为字节流 字符流
- 1字符 = 2字节 1字节(byte) = 8位(bit) 一个汉子占两个字节长度
- 字节流:每次读取(写出)一个字节 当传输的资源文件有中文时, 就会出现乱码
- 字符流:每次读取(写出)两个字节 当有中文时,使用该流就可以正确传输显示中文
-
按功能不同分为节点流*处理流
- 节点流:以从或向一个特定的地方(节点)读写数据 如: FileInputStream
- 处理流:是对一个已存在的流的连接和封装 通过所封装的流的功能调用实现数据读写 如:BufferedReader 处理流的构造方法总是要带一个其他的流对象做参数. 一个流对象经过其他流的多次包装
-
4个基本的抽象流类型 所有的流都继承这4个
输入流 | 输出流 | |
---|---|---|
字节流 | InputStream | outputStream |
字符流 | Reader | Writer |
IO流特性
- 先进先出 最先写入输出流的数据最先被输入流读取到
- 顺序存取 可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随即访问中间的数据
- 只读或只写 每个流只能是输入流或输出流的一种 不能同时具备两个功能 输入流只能进行读操作,对输出流只能进行写操作在一个数据传输通道中,如果既要写入数据 又要读取数据,则要分别提供两个流
IO流常用到的五类一接口
- 5个类:File OutputStream InputStream Write Reader,一个接口Serializable
- 输入字节流InputStream
- ByteArrayInputStream:字节数组输入流, 该类的功能就是从字节(Byte[])中进行以字节为单位的读取,也就是将资源文件都以字节的形式存入到该类中的字节数组中去
- PipeInputStream:管道字节输入流 与PipeOutputStream一起使用,能够实现多线程间的管道通信
- FileInputStream:装饰者模式中处于装饰者,具体的装饰者都要继承它,所以在该类的子类下都是用来装饰别的流,也就是处理类,
- BufferedInputStream:缓冲流 对处理流进行装饰 增强,内部会有一个缓存区 用来存放字节 每次都是将缓存区存满然后发送,而不是一个字节或两个字节发送 效率更高
- DataInputStream:数据输入流 它用来装饰其他输入流 “允许应用程序以与及其无关方式从底层输入流中读取最基本的Java数据类型”
- FileInputStream:文件输入流 对文件进行读取操作
- File: 对指定目录进行操作
- ObjectInputStream:对象输入流 用来提供对"基本数据或对象"的处理存储
字节流和字符流使用情况
- 字符流和字节流使用范围:字节流一般用来处理图像 视频 以及ppt Word类型文件 字符流一般用于处理纯文本类型文件 如TXT文件等 字节流可以用来处理纯文本文件 但字符流不能用于处理图像视频等非文本类型文件
- InputStreamReader: 字节到字符的桥梁 将字节流以字符流输入
- OutputStreamWriter:字符到字节的桥梁 将字节流以字符流输出
- 字节流没有缓冲区,是直接输出的 而字符流是输出到缓冲区的, 因此在输出时 字节流不调用close()方法时,信息已经输出了 而字符流只有在调用close()方法关闭缓冲区时,信息才输出.要想字符流在未关闭时输出信息,则需要手动调用flush()方法
TCP
-
客户端
- 连接服务器Socket
- 发送消息
-
服务器
- 建立服务的端口ServerSocket
- 等待用户的链接accept
- 接收用户的消息
package com.wu.network;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
//客户端
public class TCPClient {
public static void main(String[] args) {
Socket socket =null;
OutputStream os =null;
//知道用户地址
try {
InetAddress serverIp = InetAddress.getByName("localhost");
//端口号
int port =9999;
//创建一个socket连接
socket = new Socket(serverIp,port);
//发送消息IO流''
os = socket.getOutputStream();
os.write("你好,连接测试".getBytes());
} catch (UnknownHostException e) {
e.printStackTrace();
} 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();
}
}
}
}
}
package com.wu.network;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TCPSever {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket =null;
InputStream is = null;
ByteArrayOutputStream bios=null;
//新建地址
try {
serverSocket = new ServerSocket(9999);
//等待客户端连接过来
socket = serverSocket.accept();
//读取客户端的消息
is = socket.getInputStream();
//管道流
bios = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while((len= is.read(buffer)) != -1){
bios.write(buffer,0,len);
}
System.out.println(bios.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
if(bios != null){
try {
bios.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}