网络编程
一. 网络基础简介
计算机网络指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
1. 通信协议
网络中的计算机与终端间要想正确的传送信息和数据,必须在数据传输的顺序、数据的格式及内容等方面有一个约定或规则,这种约定或规则称做通信协议。
为了分析网络通讯,引进了一套OSI模型理论。
1.1 OSI模型
数据由传送端的最上层(通常是指应用程序)产生,由上层往下层传送。每经过一层,都会在前端增加一些该层专用的信息,这些信息称为“报头”,然后才传给下一层,我们不妨将“加上报头”想象为“套上一层信封”。因此到了最底层时,原本的数据已经套上了7层信封。而后通过网络线、电话线、光缆等媒介,传送到接收端。
接收端收到数据后,会从最底层向上层传送,每经过一层就拆掉一层信封(亦即去除该层所识别的报头),直到了最上层,数据便恢复成当初从传送端最上层产生时的原貌。
1.2常用通讯协议
2. TCP与UDP区别总结
二. Socket通信
1. 简介
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket,又称”套接字”。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,即为Socket编程接口。
2. TCP Socket模型
TCP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt(); * 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、开启监听,用函数listen();
5、接收客户端上来的连接,用函数accept();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
8、关闭监听;
TCP编程的客户端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置要连接的对方的IP地址和端口等属性;
5、连接服务器,用函数connect();
6、收发数据,用函数send()和recv(),或者read()和write();
7、关闭网络连接;
【示例】
1. socket服务端
public class TestTCPServer01 {
public static void main(String[] args) throws Exception {
// 1、创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket ss = new ServerSocket(8888);
while (true) {
// 2、调用accept()方法开始监听,等待客户端的连接
Socket socket = ss.accept();
System.out.println("client" + " connect!");
// 3、获取输入流,并读取客户端信息
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("Hello,i'm server,client say:" + info);
}
br.close();
}
}
}
2. socket客户端
public class TestTCPClient01 {
public static void main(String[] args) throws Exception {
// 1、创建客户端Socket,指定服务器地址和端口
Socket s = new Socket("127.0.0.1", 8888);
// 2、获取输出流,向服务器端发送信息
OutputStream os = s.getOutputStream();
// 将输出流包装成打印流
PrintWriter pw = new PrintWriter(os);
pw.write("hello,i'm 天亮!");
pw.flush();
pw.close();
}
}
3. UDP Socket模型
UDP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();
4、循环接收数据,用函数recvfrom();
5、关闭网络连接;
UDP编程的客户端一般步骤是:
1、创建一个socket,用函数socket();
2、设置socket属性,用函数setsockopt();* 可选
3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
4、设置对方的IP地址和端口等属性;
5、发送数据,用函数sendto();
6、关闭网络连接;
【示例】
- udp服务端
public class TestUDPServer01 {
public static void main(String args[]) throws Exception {
//创建一个socket
DatagramSocket ds = new DatagramSocket(7777);
//创建一个数据包
byte buf[] = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//阻塞等待接收客户端发送的数据包
ds.receive(dp);
//数据包中携带的数据在数据包的buf字节数组中,将其转换成字符串
String para = new String(buf, "utf-8");
//打印传递的数据
System.out.println("client print=" + para);
}
}
- udp客户端
public class TestUDPClient01 {
public static void main(String args[]) throws Exception {
// 创建socket对象
DatagramSocket ds = new DatagramSocket();
// 创建指定端口的ip地址
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 7777);
// 把要发送的数据转换成字节数组形式
String sendStr = "i'm 天亮 Thanks for your coming! Come on!";
byte[] buf = sendStr.getBytes("utf-8");
// 创建数据包,封装字节数组数据和目标ip地址
DatagramPacket dp = new DatagramPacket(buf, buf.length, inetSocketAddress);
// 发送数据包
ds.send(dp);
// 关闭socket
ds.close();
System.out.println("send done!");
}
}
实例程序 :
- TCP传输
package com;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 网络架构 : B/S和C/S
*
* B/S : Browser/Server,基于浏览器进行交互,比如网页版淘宝
*
* C/S : Client/Server,基于客户端进行交互,比如下载安装的淘宝APP
*
* TCP :
*
* 能重传,不丢包,有序 可靠 面向连接 请求需要来回往返,简称三次握手
*
* UDP :
*
* 速度快 不保证可靠 可能丢包 无连接
*
* @author lenovo
* @date 2020年7月22日
*/
public class _01_TCPServer {
public static void main(String[] args) throws IOException {
// 开启端口
ServerSocket ss = new ServerSocket(10000);
System.out.println("服务器已启动,正在等待客户连接...");
// 执行这个方法的时候,就会停下来,一直到有客户连接位置
// 有客户连接之后,skt 就保存客户端对象
Socket skt = ss.accept();
System.out.println("客户已连接");
// 获取客户端输入的数据流
InputStream fis = skt.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(fis, "gbk"));
// 读取客户输入的数据
String line = br.readLine();
System.out.println(line);
// 获取输出流和打印流,把数据返回给客户端
PrintWriter out = new PrintWriter(new OutputStreamWriter(skt.getOutputStream(), "gbk"));
out.println("-----------");
out.close();
br.close();
fis.close();
skt.close();
ss.close();
System.out.println("连接已关闭");
}
}
package com;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class _02_TCPClient {
public static void main(String[] args) throws Exception {
// 创建连接,需要传入IP和端口
Socket skt = new Socket("127.0.0.1", 10000);
// 获取流 向服务端发送数据
PrintWriter out = new PrintWriter(new OutputStreamWriter(skt.getOutputStream(), "gbk"));
out.println("啥也不是");
out.flush();
// 获取输入流,接收服务端返回的数据
InputStream fis = skt.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(fis, "gbk"));
System.out.println(br.readLine());
br.close();
out.close();
skt.close();
}
}
- UDP 传输 :
package com;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class _03_UDPServer {
public static void main(String[] args) throws IOException {
// 打开 UDP 对象,并监听某个端口,用于数据接收
DatagramSocket ds = new DatagramSocket(10000);
// 声明一个数组,存放保存的数据
byte[] buf = new byte[1024];
// 包接收器
DatagramPacket dp = new DatagramPacket(buf, buf.length);
while (true) {
// 接受数据
ds.receive(dp);
System.out.println(new String(buf));
// ByteArrayInputStream bais = new ByteArrayInputStream(buf);
// DataInputStream dis = new DataInputStream(bais);
// System.out.println(dis.readUTF());
}
}
}
package com;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.Scanner;
public class _04_UDPClient {
public static void main(String[] args) throws IOException {
// 1
String string = null;
Scanner sc = new Scanner(System.in);
string = sc.nextLine();
while (!string.trim().equals(" ")) {
// 把数据拆分成字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeUTF(string);
// 把数据写入字节数组中
// byte[] buf = baos.toByteArray();
byte[] buf = string.getBytes();
// 数据传输
// 数据包
DatagramPacket dp = new DatagramPacket(buf, buf.length, new InetSocketAddress("127.0.0.1", 10000));
// 开启端口,把包发送出去
DatagramSocket ds = new DatagramSocket();
ds.send(dp);
ds.close();
// 再次接收控制台输入
string = sc.nextLine();
}
System.out.println("退出");
}
}