[TOC]
0x00 网络编程 1) 介绍概述 1.概述
计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程:就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
网络编程三要素:IP / 端口(Port) / 协议(protocol) 补充知识: 3G/4G 通过信号塔,有的信号塔连接的是卫星通信;
2.IP概述
每个设备在网络中的唯一标识,每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
本地回路地址:127.0.0.1 255.255.255.255是广播地址
IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
IPv6:8组,每组4个16进制数。
1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f
1a2b::aaaa:0000:0000:0000:aabb:1f2f
1a2b:0000:aaaa::aabb:1f2f
1a2b:0000:aaaa::0000:aabb:1f2f
1a2b:0000:aaaa:0000::aabb:1f2f
3.端口号概述
每个程序在设备上的唯一标识,每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。类比于您在什么年级/什么班/位置号
端口号范围从0-65535 (Windows )
编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
常用端口:
[TOC]
0x00 网络编程 1) 介绍概述 1.概述
计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程:就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
网络编程三要素:IP / 端口(Port) / 协议(protocol) 补充知识: 3G/4G 通过信号塔,有的信号塔连接的是卫星通信;
2.IP概述
每个设备在网络中的唯一标识,每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址。
本地回路地址:127.0.0.1 255.255.255.255是广播地址
IPv4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。
IPv6:8组,每组4个16进制数。
1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f
1a2b::aaaa:0000:0000:0000:aabb:1f2f
1a2b:0000:aaaa::aabb:1f2f
1a2b:0000:aaaa::0000:aabb:1f2f
1a2b:0000:aaaa:0000::aabb:1f2f
3.端口号概述
每个程序在设备上的唯一标识,每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序。类比于您在什么年级/什么班/位置号
端口号范围从0-65535 (Windows )
编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统程序占用了。
常用端口:1 2 3 4 5 6 * mysql: 3306 * oracle: 1521 * web: 80 * tomcat: 8080 * QQ: 4000 * feiQ: 2425
4.协议概述 为计算机网络中进行数据交换而建立的规则、标准或约定的集合。
UDP
面向无连接,数据不安全,速度快。不区分客户端与服务端。 (发短信)
TCP
面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。(打电话)
三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据
2) Socket通信原理 Socket套接字概述:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO流传输。
Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port
。可以类比为码头和集装箱以及货运船只;
3) UDP传输与优化 使用的类:1 2 public class DatagramSocket extends Object implements Closeable public final class DatagramPacket extends Object
UDP-Socket构建发送流程: 1.发送Send
创建DatagramSocket, 随机端口号
创建DatagramPacket, 指定数据, 长度, 地址, 端口
使用DatagramSocket.send()发送DatagramPacket
关闭DatagramSocket.close()
2.接收Receive
创建DatagramSocket, 指定端口号
创建DatagramPacket, 指定数组, 长度
使用DatagramSocket.receive接收DatagramPacket
关闭DatagramSocket.close()
从DatagramPacket中获取数据
3.接收方获取ip和端口号1 2 String ip = packet.getAddress().getHostAddress(); int port = packet.getPort();
实际案例1:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package com.weiyigeek.net;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.util.Scanner;public class Demo1_UDPSend { public static void main (String[] args) throws Exception { Scanner sc = new Scanner(System.in); DatagramSocket udpsocket = new DatagramSocket(); while (true ) { String str = sc.nextLine(); DatagramPacket pt = new DatagramPacket(str.getBytes(), str.getBytes().length,InetAddress.getByName("127.0.0.1" ), 8888 ); udpsocket.send(pt); if (str.equals("quit" )) break ; } udpsocket.close(); } } package com.weiyigeek.net;import java.net.DatagramPacket;import java.net.DatagramSocket;public class Demo1_UDPReceive { public static void main (String[] args) throws Exception { DatagramSocket udpsocket = new DatagramSocket(8888 ); DatagramPacket udppacket = new DatagramPacket(new byte [1024 ], 1024 ); while (true ) { udpsocket.receive(udppacket); byte [] arr = udppacket.getData(); int len = udppacket.getLength(); String ip = udppacket.getAddress().getHostAddress(); int port = udppacket.getPort(); System.out.println(ip+":" + port + " = " + new String(arr,0 ,len)); if (new String(arr,0 ,len).equals("quit" )) { break ; } } udpsocket.close(); } }
执行结果:1 2 3 4 whoami Iloveyou WeiyiGeek quit
weiyigeek.top-
实际案例2:多线程实现一个窗口接和发数据1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 package com.weiyigeek.net;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.util.Scanner;public class Demo2_ReceSend { public static void main (String[] args) { new receive().start(); new send().start(); } } class receive extends Thread { @Override public void run () { try { DatagramSocket ss = new DatagramSocket(8888 ); DatagramPacket pt = new DatagramPacket(new byte [1024 ], 1024 ); while (true ) { ss.receive(pt); byte [] arr = pt.getData(); int len = pt.getLength(); String ip = pt.getAddress().getHostAddress(); int port = pt.getPort(); String msg = new String(arr,0 ,len); System.out.println(ip + ":" + port + "\n" + msg); if (msg.equals("quit" )) { System.out.println("接收端停止-Recevice Stop" ); break ; } } ss.close(); } catch (Exception e) { } } } class send extends Thread { @Override public void run () { Scanner sc = new Scanner(System.in); try { DatagramSocket ss = new DatagramSocket(); while (true ){ String msg = sc.nextLine(); DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.getBytes().length, InetAddress.getByName("127.0.0.1" ), 8888 ); ss.send(dp); if (msg.equals("quit" )) { System.out.println("发送端停止-Send Stop" ); break ; } } ss.close(); } catch (Exception e) { System.out.println(e.getMessage()); } } }
执行结果:1 2 3 4 5 quit 发送端停止-Send Stop 127.0 .0.1:51090 quit 接收端停止-Recevice Stop
4) TCP传输与优化 1.客户端Client
创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
输入流可以读取服务端输出流写出的数据
输出流可以写出数据到服务端的输入流
2.服务端Server
创建ServerSocket(需要指定端口号)
调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
输出流可以写出数据到客户端的输入流
输入流可以读取客户端输出流写出的数据
CS对应表: 客户端 C | 服务端 S —|— getInputStream | getOutputStream getOutoutStream | getInputStream
实际案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package com.weiyigeek.net;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class Demo3_TcpSend { public static void main (String[] args) throws Exception { Socket client = new Socket("127.0.0.1" ,9999 ); InputStream is = client.getInputStream(); OutputStream os = client.getOutputStream(); byte [] arr = new byte [1024 ]; int len = is.read(arr); System.out.println(new String(arr,0 ,len)); os.write("我是客户端发来得消息!" .getBytes()); client.close(); } } package com.weiyigeek.net;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class Demo3_TcpReiceve { public static void main (String[] args) throws Exception { ServerSocket ss = new ServerSocket(9999 ); Socket socket = ss.accept(); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); os.write("这是从服务端发送得信息" .getBytes()); byte [] arr = new byte [1024 ]; int len = is.read(arr); System.out.println(new String(arr,0 ,len)); socket.close(); } }
weiyigeek.top-
实际案例: TCP服务端多线程及其优化1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.weiyigeek.net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;public class Demo3_TcpSend { public static void main (String[] args) throws IOException { Socket socket = new Socket("127.0.0.1" , 8888 ); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()); System.out.println(br.readLine()); ps.println("2.我是客户端的反馈信息!" ); System.out.println(br.readLine()); ps.println("4.客户端的通信结束!" ); socket.close(); } } package com.weiyigeek.net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.ServerSocket;import java.net.Socket;public class Demo3_TcpReceive { private static ServerSocket ss; public static void main (String[] args) throws Exception { ss = new ServerSocket(8888 ); while (true ){ final Socket socket = ss.accept(); new Thread() { public void run () { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println("1.我是服务端发出的信息!" ); System.out.println(br.readLine()); ps.println("3.服务端请求客户端关闭通信" ); System.out.println(br.readLine()); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
weiyigeek.top-
5) 网络编程练习 练习1: 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串;
客户端:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.weiyigeek.net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;import java.util.Scanner;public class Demo4_Client { public static void main (String[] args) throws Exception, IOException { Socket socket = new Socket("127.0.0.1" ,8888 ); Scanner sc = new Scanner(System.in); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()); System.out.print("请输入您要发送的字符串:" ); ps.println(sc.nextLine() ); System.out.println("服务端翻转后的字符串:" + br.readLine()); socket.close(); } }
服务端:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.weiyigeek.net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.ServerSocket;import java.net.Socket;public class Demo4_Server { public static void main (String[] args) throws Exception, IOException { ServerSocket ss = new ServerSocket(8888 ); while (true ){ final Socket sc = ss.accept(); new Thread() { public void run () { try { BufferedReader br = new BufferedReader(new InputStreamReader(sc.getInputStream())); PrintStream ps = new PrintStream(sc.getOutputStream()); StringBuffer sendMsg = new StringBuffer(br.readLine()).reverse(); System.out.println("服务端翻转客户端发送的字符串:" + sendMsg); ps.println(sendMsg); sc.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
weiyigeek.top-
练习2: 客户端向服务器上传文件
客户端:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 package com.weiyigeek.net;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.Socket;import java.util.Scanner;public class Demo5_Client { public static void main (String[] args) throws Exception, IOException { File upFile = getFile(); Socket client = new Socket("127.0.0.1" ,9999 ); BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream())); PrintStream ps = new PrintStream(client.getOutputStream()); System.out.println("正在向服务端发送将要上传的文件名称:" + upFile.getName()); ps.println(upFile.getName()); String res = br.readLine(); System.out.println(res); if (res.equals("Found" )) { System.out.println("服务端已经存在该文件请不要重新上传,即将关闭Client Socket!" ); client.close(); return ; }else { System.out.println("服务端不存在该文件正在上传!" ); } FileInputStream fis = new FileInputStream(upFile); byte [] arr = new byte [8192 ]; int len; while ((len = fis.read(arr)) != -1 ) { ps.write(arr, 0 , len); } fis.close(); client.close(); } private static File getFile () { Scanner sc = new Scanner(System.in); System.out.print("请输入您要上传的文件路径: " ); while (true ){ String line = sc.nextLine(); File path = new File(line); if (!path.exists()) { System.out.println("文件不存在请重新输入: " ); }else if (path.isDirectory()){ System.out.println("您输入的路径是目录不是文件请重新输入: " ); }else { return path; } } } }
服务端:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package com.weiyigeek.net;import java.io.BufferedReader;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.ServerSocket;import java.net.Socket;public class Demo5_Server { public static void main (String[] args) throws Exception { ServerSocket ss = new ServerSocket(9999 ); System.out.println("服务器已启动绑定端口 : 9999 --- run" ); while (true ) { final Socket res = ss.accept(); new Thread() { public void run () { try { InputStream is = res.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintStream ps = new PrintStream(res.getOutputStream()); String fileName = br.readLine(); File dir = new File("update" ); dir.mkdir(); File file = new File(dir,fileName); if (file.exists()) { ps.println("Found" ); res.close(); }else { ps.println("NotFound" ); } FileOutputStream fos = new FileOutputStream(file); byte [] arr = new byte [8192 ]; int len; while ((len = is.read(arr)) != -1 ) { fos.write(arr,0 ,len); } System.out.println(file.getName() +"文件上传成功!" ); fos.close(); res.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
weiyigeek.top-