网络编程概述
计算机网络:
网络模型(OSI开放式系统互联。国际标准组织制定了OSI七层网络模型(Open System Interconnection)模型):
物理层 数据链路层 网络层 传输层 会话层 表示层 应用层
协议:事先规定好的通信规则
协议分类:共有的,私有的
网络层:ip
传输层:udp,tcp
应用层:ftp http https。。。
注意:
udp快,不保证数据安全
tcp保证安全,但效率没有udp高
http:响应成功,连接断开
ftp:一直连接着,要下载和上传数据
IP地址:表示网络上的唯一一台计算机
IP地址分为两个版本:
IPv4:表示网络上的计算机,范围太小,32位
IPv6:128位
端口:标识服务器的一个功能
端口:0-65535 (0-1024)预留的
同一台机器上不能有两个程序使用同一个端口
域名解析:解析成ip地址
如:localhost是域名,解析的ip地址为127.0.0.1
访问网站的过程:
先将域名解析成ip地址,找ip地址对应的服务器
服务区把网页上的东西通过流送到客户端浏览器
浏览器有解析html的,此时就可以访问到页面
java中的网络编程
1.UDP通信 – 写信
-
不需要创建连接
-
通过发送数据包通信 每个数据包最大64KB
-
不可靠的传输机制
-
传输速度比较快
-
追求速度快 可靠性要求不高的场景下 - 视频聊天
public class DemoReceive {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
DatagramSocket ds=new DatagramSocket(666);
byte b[]=new byte[1024];
DatagramPacket dp=new DatagramPacket(b,b.length);
ds.receive(dp);
String msg=new String(dp.getData(),0,dp.getLength());
System.out.println(msg);
ds.close();
}
}
public class DemoSend {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
DatagramSocket ds=new DatagramSocket();
String b="hello";
DatagramPacket dp=new DatagramPacket(b.getBytes(),b.length());
dp.setSocketAddress(new InetSocketAddress("localhost",666));
ds.send(dp);
ds.close();
}
}
2.TCP通信 – 打电话
需要先创建连接 - 并且在创建连接的过程中 需要经过三次握手
底层通过 流 发送数据 数据没有大小限制
可靠的传输机制 - 丢包重发 包的顺序的保障
传输速度相对比较慢
对于速度要求不太高 但是对可靠性要求比较高的场景下 - 文件上传 下载
因为TCP在通信的过程中 是需要创建连接的 连接的发起者称为客户端 监听端口等待被连接的一端称为服务端
服务器端的核心代码
public class DemoServe {
public static void main(String[] args) throws IOException{
//1.创建套接字对象
ServerSocket ss=new ServerSocket(555);
System.out.println("等待客户端的请求。。");
//2.调用accept方法,接收请求
Socket s=ss.accept();
//3.获取输入流对象,读客户端的数据
InputStream in=s.getInputStream();
BufferedReader b=new BufferedReader(new InputStreamReader(in));
String msg=b.readLine();
System.out.println(msg);
//4.处理后的结果,通过输出流写出去
msg=msg+"hello,client";
OutputStream o=s.getOutputStream();
//PrintWriter既可以放字符,也可以放字节
PrintWriter p=new PrintWriter(o);
p.println(msg);
p.flush();
//5.关闭流,套接字对象
in.close();
o.close();
ss.close();
s.close();
}
}
客户端的代码:
public class DemoClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//1.创建套接字对象
Socket s=new Socket("localhost",555);
//2.获取输出流,写信息
OutputStream o=s.getOutputStream();
PrintWriter p=new PrintWriter(o);
p.println("hello");
p.flush();
//3.获取输入流,读信息
InputStream in=s.getInputStream();
BufferedReader b=new BufferedReader(new InputStreamReader(in));
String msg=b.readLine();
System.out.println(msg);
//4.关闭流
in.close();
o.close();
s.close();
}
}
结果:
DemoServe:
等待客户端的请求。。
hello
DemoClient:
hellohello,client
案例(了解):实现 文件 上传服务器
public class DemoUploadClient {
public static void main(String[] args) throws IOException {
//1.创建套接字对象
Socket socket = new Socket("127.0.0.1",4444);
//2.输出流输入数据文件内容
OutputStream out = socket.getOutputStream();
//4 表示数据文件的文件名的长度
//read_v1.txt表示文件名
//[11\r\nread_v1.txt100\r\n代码修正....]
File file = new File("read_v1.txt");
//文件名的长度
//http表示1行结束:"\r\n"
out.write((file.getName().getBytes().length+"\r\n").getBytes());
//文件名
out.write(file.getName().getBytes());
//文件的长度
out.write((file.length()+"\r\n").getBytes());
//写文件内容
FileInputStream fileIn =
new FileInputStream(file);
byte[] buff = new byte[(int)file.length()];
fileIn.read(buff);
fileIn.close();
out.write(buff);
//5.接收服务器端的响应
InputStream in = socket.getInputStream();
BufferedReader br =
new BufferedReader(
new InputStreamReader(in));
String msg = br.readLine();
System.out.println(msg);
//6.close();
out.close();
in.close();
br.close();
socket.close();
}
}
public class DemoUploadServer {
public static void main(String[] args) throws IOException {
//1.创建套接字对象
ServerSocket serverSocket = new ServerSocket(4444);
Socket socket = serverSocket.accept();
//2.获取输入流对象,解析数据
InputStream in = socket.getInputStream();
byte[] b = new byte[1];
String str = "";
while(!str.endsWith("\r\n")){
in.read(b);
//一次只读一个,进行字符串连接
str += new String(b);
}
//str="11\r\n";[0,2)
int fileNameLen =
Integer.parseInt(str.substring(0, str.length()-2));
byte[] fileNameArr= new byte[fileNameLen];
in.read(fileNameArr);
//文件名
String fileName = new String(fileNameArr);
byte[] b2 = new byte[1];
String str2 = "";
while(!str2.endsWith("\r\n")){
in.read(b2);
str2 += new String(b2);
}
//str2="100\r\n"
int fileLen =
Integer.parseInt(str2.substring(0, str2.length()-2));
byte[] fileArr = new byte[fileLen];
in.read(fileArr);
//3.创建文件的输出流,把数据文件的数据(byte)写到upload文件夹下,文件名为
// 原数据文件的名字
FileOutputStream fileOut =
new FileOutputStream("upload/"+fileName);
fileOut.write(fileArr);
fileOut.close();
//4.使用输出流响应客户端的请求"上传成功!"
OutputStream out =
socket.getOutputStream();
PrintStream pw =
new PrintStream(out);
pw.println("上传成功!");
pw.flush();
//5.关闭流,套接字对象
pw.close();
socket.close();
serverSocket.close();
}
}
练习:
v1
1.定义成员变量套接字
2.在构造方法中初始化
3.start方法处理读写
4.main方法创建对象,调用start方法
public class Client {
private Socket socket;
public Client(){
try {
socket = new Socket("localhost",5555);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start() throws IOException{
//2.获取输出流,写信息
OutputStream out =
socket.getOutputStream();
PrintStream pw =
new PrintStream(out);
pw.println("hello server!");
pw.flush();
//3.获取输入流,读信息
InputStream in = socket.getInputStream();
BufferedReader br =
new BufferedReader(
new InputStreamReader(in));
String msg = br.readLine();
System.out.println(msg);
//4.关闭流
pw.close();
br.close();
socket.close();
}
public static void main(String[] args) throws IOException {
new Client().start();
}
}
public class Server {
private ServerSocket serverSocket;
public Server(){
try {
serverSocket=
new ServerSocket(5555);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start() throws IOException{
System.out.println("等待客户端的请求。。。。。");
//2.调用accept方法,接收请求
Socket socket = serverSocket.accept();
System.out.println("接收到一个客户端的请求。。。。。。");
//3.获取输入流对象,读客户端的数据
InputStream in = socket.getInputStream();
BufferedReader br =
new BufferedReader(
new InputStreamReader(in));
String msg = br.readLine();
System.out.println(msg);
//4.处理后的结果通过输出流,写出去
msg = msg+ " hello,client!";
OutputStream out =
socket.getOutputStream();
PrintStream pw =
new PrintStream(out);
pw.println(msg);
pw.flush();
//5.关闭流,套接字对象
br.close();
pw.close();
socket.close();
serverSocket.close();
}
public static void main(String[] args) throws IOException {
new Server().start();
}
}
v2
控制台一对一会话
在客户端实现接收控制台输入
public class Client {
private Socket socket;
public Client(){
try {
socket = new Socket("localhost",5555);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void start() throws IOException{
//2.获取输出流,写信息
OutputStream out =
socket.getOutputStream();
PrintStream pw =
new PrintStream(out);
Scanner sc = new Scanner(System.in);
System.out.println("Input:");
String msg = sc.next();
pw.println(msg);
pw.flush();
//3.获取输入流,读信息
InputStream in = socket.getInputStream();
BufferedReader br =
new BufferedReader(
new InputStreamReader(in));
msg = br.readLine();
System.out.println(msg);
//4.关闭流
pw.close();
br.close();
socket.close();
}
public static void main(String[] args) throws IOException {
new Client().start();
}
}
v3
一个客户端和服务器多次会话
客户端使用while循环输入
服务器端使用while循环接收数据