一、网络编程
计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。网络编程就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
1.IP概述
每个设备在网络中的唯一标识,每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
IPv6:8组,每组4个16进制数。
2.端口号
每个程序在设备上的唯一标识,每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。端口号范围从0-65535,编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
3.协议
为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
UDP 用户数据报协议,类似写信,面向无连接,数据不安全,速度快。不区分客户端与服务端。是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
TCP 传输控制协议,类似打电话,面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据。
提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
4.Socket
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO流传输。Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。
5.UDP
1.发送Send
创建DatagramSocket,随机端口号
创建DatagramPacket,指定数据,长度,地址,端口
使用DatagramSocket发送DatagramPacket
关闭DatagramSocket
2.接收Receive
创建DatagramSocket,指定端口号
创建DatagramPacket,指定数组,长度
使用DatagramSocket接收DatagramPacket
关闭DatagramSocket
3.接收方获取ip和端口号
String ip = packet.getAddress().getHostAddress();
int port = packet.getPort();
6.UDP传输优化
接收端Receive
DatagramSocket socket = new DatagramSocket(6666); //相当于创建码头
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); //创建packet相当于创建集装箱
while(true) {
socket.receive(packet); //接收货物
byte[] arr = packet.getData();
int len = packet.getLength();
String ip = packet.getAddress().getHostAddress();
System.out.println(ip + ":" + new String(arr,0,len));
}
发送端Send
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
if("quit".equals(str)) break;
DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
socket.send(packet);
}
socket.close();
7.UDP传输多线程
发送和接收在一个窗口完成
public class Demo3MoreThread {
public static void main(String[] args) {
new Receive().start();
new Send().start();
}
}
class Receive extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(6666);
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
while(true) {
socket.receive(packet);
byte[] arr = packet.getData();
int len = packet.getLength();
String ip = packet.getAddress().getHostAddress();
System.out.println(ip + ":" + new String(arr,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Send extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
if("quit".equals(str))
break;
DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
socket.send(packet);
}
socket.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
二、TCP协议
1.客户端
创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
输入流可以读取服务端输出流写出的数据
输出流可以写出数据到服务端的输入流
2.服务端
创建ServerSocket(需要指定端口号)
调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
输入流可以读取客户端输出流写出的数据
输出流可以写出数据到客户端的输入流
3.TCP协议代码优化
客户端
Socket socket = new Socket("127.0.0.1", 9999);
InputStream is = socket.getInputStream(); //获取输入流
OutputStream os = socket.getOutputStream(); //获取输出流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(os);
System.out.println(br.readLine());
ps.println("我想报名就业班");
System.out.println(br.readLine());
ps.println("爷不学了");
socket.close();
服务端
ServerSocket server = new ServerSocket(9999); //创建服务器
Socket socket = server.accept(); //接受客户端的请求
InputStream is = socket.getInputStream(); //获取输入流
OutputStream os = socket.getOutputStream(); //获取输出流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
PrintStream ps = new PrintStream(os);
ps.println("欢迎咨询传智播客");
System.out.println(br.readLine());
ps.println("报满了,请报下一期吧");
System.out.println(br.readLine());
server.close();
socket.close();
4.服务端是多线程
ServerSocket server = new ServerSocket(9999); //创建服务器
while(true) {
final Socket socket = server.accept(); //接受客户端的请求
new Thread() {
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("欢迎咨询传智播客");
System.out.println(br.readLine());
ps.println("报满了,请报下一期吧");
System.out.println(br.readLine());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}