网络编程介绍
- 计算机网络
- 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
- 网络编程
- 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
网络编程三要素
IP地址
- 每个设备在网络中的唯一标识
- 每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
- ipconfig:查看本机IP192.168.12.42
- ping:测试连接192.168.40.62
- 本地回路地址:127.0.0.1 255.255.255.255是广播地址
- IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
- IPv6:8组,每组4个16进制数。
端口号
- 每个程序在设备上的唯一标识
- 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。
- 端口号范围从0-65535
- 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
协议
- 为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
- UDP
- 面向无连接,数据不安全,速度快。不区分客户端与服务端。
- TCP
* 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
- 三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据
网络编程入门
Socket通信
- Socket套接字概述:
- 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
- 通信的两端都有Socket。
- 网络通信其实就是Socket间的通信。
- 数据在两个Socket间通过IO流传输。
- Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port。
UDP协议
- 1.发送Send
- 创建DatagramSocket, 随机端口号
- 创建DatagramPacket, 指定数据, 长度, 地址, 端口
- 使用DatagramSocket发送DatagramPacket
- 关闭DatagramSocket
- 2.接收Receive
- 创建DatagramSocket, 指定端口号
- 创建DatagramPacket, 指定数组, 长度
- 使用DatagramSocket接收DatagramPacket
- 关闭DatagramSocket
- 从DatagramPacket中获取数据
- 3.接收方获取ip和端口号
- String ip = packet.getAddress().getHostAddress();
- int port = packet.getPort();
代码
/**
* UDP编程
*/
public class TestUDP {
//发送端
@Test
public void send(){
DatagramSocket socket = null;
DatagramPacket packet = null;
try {
//创建socket对象
socket = new DatagramSocket();
String str = "发送的数据";
byte[] buf = str.getBytes();
//创建一个数据报:每一个数据报不能大于64k,都记录着数据信息,发送端的IP、端口号、以及要发送到的接收端的IP、端口号
packet = new DatagramPacket(buf, 0, buf.length, InetAddress.getByName("127.0.0.1"),9000);
socket.send(packet);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
socket.close();
}
}
}
//接收端
@Test
public void receive(){
DatagramSocket socket = null;
try {
//创建socket对象
socket = new DatagramSocket(9000);
byte[] b = new byte[1024];
DatagramPacket packet = new DatagramPacket(b,0, b.length);
//接收报文
socket.receive(packet);
String str = new String(packet.getData(),0,packet.getLength());
System.out.println(str);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
socket.close();
}
}
}
}
UDP(多线程)
public class Demo3_MoreThread {
/**
* @param args
*/
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); //创建socket相当于创建码头
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));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Send extends Thread {
public void run() {
try {
DatagramSocket socket = new DatagramSocket(); //创建socket相当于创建码头
Scanner sc = new Scanner(System.in);
while(true) {
String str = sc.nextLine();
if("quit".equals(str))
break;
DatagramPacket packet = //创建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流
- 输入流可以读取客户端输出流写出的数据
- 输出流可以写出数据到客户端的输入流
代码
客户端给服务端发送信息
/**
* tcp编程,客户端给服务端发送信息
*/
public class TestTCP2 {
//客户端
@Test
public void client(){
Socket socket = null;
OutputStream os = null;
InputStream is = null;
try {
//1.创建一个socket对象,通过构造器指明服务端ip地址以及其接收的端口号
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2.获取输出流
os = socket.getOutputStream();
//3.发送信息
os.write("客户端".getBytes());
//发送完毕
socket.shutdownOutput();
//收到服务端信息
is = socket.getInputStream();
byte[] b = new byte[20];
int len;
while ((len = is.read(b)) != -1) {
String str = new String(b,0,len);
System.out.println(str);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.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();
}
}
}
}
//服务端
@Test
public void server(){
ServerSocket ss = null;
Socket socket = null;
InputStream is = null;
OutputStream os = null;
try {
//1.创建ServerSocket对象,通过构造器指明自身端口号
ss = new ServerSocket(9000);
//2.调用accept方法,返回socket对象
socket = ss.accept();
//3.获取从客户端发过来的输入流
is = socket.getInputStream();
byte[] b = new byte[20];
int len;
while ((len = is.read(b)) != -1) {
String str = new String(b,0,len);
System.out.println(str);
}
os = socket.getOutputStream();
os.write("服务端收到".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
发送文件
/**
* tcp编程,发送文件
*/
public class TestTCP3 {
//客户端
@Test
public void client(){
Socket socket = null;
OutputStream os = null;
FileInputStream fis = null;
InputStream is = null;
try {
//1.创建socket对象
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2.读取文件,并发送给服务端
os = socket.getOutputStream();
fis = new FileInputStream(new File("test.jpg"));
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != -1) {
os.write(b,0,len);
}
//发送文件结束
socket.shutdownOutput();
//3.接收从服务端发送的信息
is = socket.getInputStream();
byte[] b1 = new byte[1024];
int len1;
while ((len1 = is.read(b1)) != -1) {
String str = new String(b1,0,len1);
System.out.println(str);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.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();
}
}
}
}
//服务端
@Test
public void server(){
ServerSocket ss = null;
Socket socket = null;
InputStream is = null;
FileOutputStream fos = null;
OutputStream os = null;
try {
//1.创建ServerSocket对象
ss = new ServerSocket(9000);
//2.获取Socket对象
socket = ss.accept();
//3.接收客户端发送的文件
is = socket.getInputStream();
fos = new FileOutputStream(new File("2.jpg"));
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1) {
fos.write(b, 0, len);
}
System.out.println("收到"+socket.getInetAddress().getHostAddress() + "发送的文件");
//4.往客户端发送消息
os = socket.getOutputStream();
os.write("接收到文件".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
URL
URL:互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址,互联网上的每个文件都有一个唯一的URL。
/**
* URL:统一资源定位符,一个url对象,对应互联网上一个资源
* 通过URL的对象调用其相应的方法,将此资源读取
*/
public class TestURL {
public static void main(String[] args) throws IOException {
//1.创建url对象
URL url = new URL("http:127.0.0.1:8080/example/test.txt");
// System.out.println(url.getProtocol());
// System.out.println(url.getHost());
// System.out.println(url.getPort());
// System.out.println(url.getFile());
// System.out.println(url.getRef());
// System.out.println(url.getQuery());
//读取客户端资源
InputStream is = url.openStream();
byte[] b = new byte[20];
int len;
while ((len = is.read(b)) != -1) {
String str = new String(b,0,len);
System.out.println(str);
}
//如果既有数据的输入,又有数据的输出
URLConnection urlConnection = url.openConnection();
InputStream is1 = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("a.txt"));
byte[] b1 = new byte[20];
int len1;
while ((len1 = is1.read(b1)) != -1) {
fos.write(b1, 0, len1);
}
//关闭资源
is.close();
is1.close();
fos.close();
}
}