网络编程
Posted Dev_Nick
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络编程相关的知识,希望对你有一定的参考价值。
网络编程
网络编程主要用于解决计算机与计算机(手机、平板..)之间的数据传输问题。
网络编程和网页编程的区别
网络编程: 不需要基于html页面就可以达到数据之间的传输。 比如: feiQ , QQ , 微信....
网页编程: 就是要基于html页面的基础上进行数据的交互的。 比如: 珍爱网、 oa(办公自动化)、 高考的报告系统...
计算机网络
指分布在不同地域的计算机,通过外部设备连接起来,实现了资源共享和数据传输的计算机系统。
网络编程的三要素:ip地址,端口号和协议。
IP地址
Internet上的每台主机(Host)都有一个唯一的IP地址。IP地址的长度为32位,分为4段,每段8位,用十进制数字表示,每段数字范围为0~255,段与段之间用句点隔开。例如159.226.1.1。(四个字节)
IP地址的类别:
IP地址是由网络号和主机号组成。即:IP地址 = 网络号+ 主机号。
A类地址:8位网络位,24位主机位 即:A类地址 = 一个网络号 + 三个主机号 2^24 政府单位
B类地址: 16位网络位,16位主机位 即:B类地址 = 两个网络号+ 两个主机号 2^16 事业单位(学校、银行..)
C类地址: 24位网络位,8位主机位 即:C类地址= 三个网络号+ 一个主机号 2^8 私人使用..
端口
如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口 可以有65536(即:2^16)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(2^16-1)。
端口的分类:
公认端口(WellKnownPorts):从0到1023,它们紧密绑定(binding)于一些服务。
注册端口(RegisteredPorts):从1024到49151。它们松散地绑定于一些服务。
动态和/或私有端口(Dynamicand/orPrivatePorts):从49152到65535。
常用端口:
21 FTP
80 HTTP
443 HTTPS
协议
协议的种类:TCP和UDP
TCP:Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议。
TCP协议的特点:
1、面向连接的协议,数据传输必须要建立连接,所以在TCP中需要连接时间。
2、传输数据大小限制,一旦连接建立,双方可以按统一的格式传输大的数据。
3、一个可靠的协议,确保接收方完全正确地获取发送方所发送的全部数据。
UDP: User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
在udp协议中,有一个IP地址称作为广播地址,广播地址就是主机号为255地址。
UDP协议的特点:
1、每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
2、UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
3、UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。
java中网络编程常用类
InetAddress:此类表示互联网协议 (IP) 地址。
常用方法:
static InetAddress
getLocalHost()
返回本地主机。
static InetAddress
getByName(String host)
在给定主机名的情况下确定主机的 IP 地址。host可以是一个主机名也可以是ip地址。
String
getHostAddress()
返回 IP 地址字符串(以文本表现形式)。
String getHostName
()
获取此 IP 地址的主机名。
Udp网络编程相关的类:DatagramSocket和DatagramPacket
DatagramSocket:此类表示用来发送和接收数据报包的套接字。
常用方法
构造方法:
DatagramSocket()
构造数据报套接字并将其绑定到本地主机上任何可用的端口。
DatagramSocket(int port)
创建数据报套接字并将其绑定到本地主机上的指定端口。
发送接收数据包方法
void
send(DatagramPacket p)
从此套接字发送数据报包。
void
receive(DatagramPacket p)
从此套接字接收数据报包。
关闭
void close()
关闭此数据报套接字。
DatagramPacket:此类表示数据报包。
常用方法
构造方法
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造数据报包,用来将长度为 length
的包发送到指定主机上的指定端口号。
DatagramPacket(byte[] buf, int length)
构造 DatagramPacket
,用来接收长度为
length
的数据包。
读取方法
byte[] getData()
返回数据缓冲区。
int getLength()
返回将要发送或接收到的数据的长度。
Udp网络编程步骤
发送端步骤:
1. 建立udp的服务。
2. 准备数据,把数据封装到数据包中发送。 发送端的数据包要带上ip地址与端口号。
3. 调用udp的服务,发送数据。
4. 关闭资源。
接收端步骤:
1. 建立udp的服务
2. 准备空的数据包接收数据。
3. 调用udp的服务接收数据。
4. 关闭资源
聊天代码示例:
1 //发送端代码 2 public class ChatSend implements Runnable{ 3 @Override 4 public void run() { 5 //从键盘读入数据打包成数据包发送 6 try { 7 //建立Udp服务 8 DatagramSocket sendScoket = new DatagramSocket(); 9 //创建数据包 10 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 11 String line = null; 12 while ((line = reader.readLine()) != null) { 13 14 System.out.println("要发送的数据是:"+line); 15 DatagramPacket sendPacket = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getLocalHost(), 9090); 16 //发送数据包 17 sendScoket.send(sendPacket); 18 } 19 //关闭服务 20 sendScoket.close(); 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } 24 } 25 } 26 //接收端代码 27 public class ChatReceive extends Thread{ 28 @Override 29 public void run() { 30 try { 31 //建立Udp服务 32 DatagramSocket receiveSocket = new DatagramSocket(9090); 33 //建立空的数据包 34 boolean flag = true; 35 while (flag) { 36 byte[] buf = new byte[1024]; 37 DatagramPacket receivePacket = new DatagramPacket(buf, buf.length); 38 receiveSocket.receive(receivePacket); 39 byte[] receiveBuf = receivePacket.getData(); 40 System.out.println("服务端收到的信息是:"+new String(receiveBuf)); 41 } 42 receiveSocket.close(); 43 } catch (Exception e) { 44 e.printStackTrace(); 45 } 46 } 47 } 48 //主方法 49 public class ChatMain { 50 public static void main(String[] args) { 51 ChatSend send= new ChatSend(); 52 Thread thread = new Thread(send); 53 thread.start(); 54 ChatReceive receive = new ChatReceive(); 55 receive.start(); 56 } 57 }
TCP网络编程涉及到的类:Socket和ServerSocket
Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
常用方法
1、构造方法
Socket(InetAddress address, int port)
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
2、普通方法
OutputStream
getOutputStream()
返回此套接字的输出流。
InputStream getInputStream()
返回此套接字的输入流。
ServerSocket:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
常用方法:
1、构造方法
ServerSocket(int port)
创建绑定到特定端口的服务器套接字。
2、普通方法
TCP的客户端使用步骤:
1. 建立tcp的客户端服务。
2. 获取到对应的流对象。
3. 写出或读取数据
4. 关闭资源。
TCP的客户端使用步骤:
1. 建立tcp服务端 的服务。
2. 接受客户端的连接产生一个Socket.
3. 获取对应的流对象读取或者写出数据。
4. 关闭资源。
实战项目:
1、相互聊天
示例代码:
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.IOException; 4 import java.io.InputStreamReader; 5 import java.io.OutputStreamWriter; 6 import java.net.InetAddress; 7 import java.net.Socket; 8 9 //客户端代码 10 public class TCPChatClient { 11 public static void main(String[] args) throws IOException { 12 //建立TCP服务 13 Socket socket = new Socket(InetAddress.getLocalHost(), 9090); 14 //获取到对应的流对象。 15 BufferedWriter socketWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 16 BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 17 BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in)); 18 String line = null; 19 while ((line = keyReader.readLine()) != null) { 20 //写出或读取数据 21 socketWriter.write(line+"\\r\\n"); 22 socketWriter.flush(); 23 String serverStr = socketReader.readLine(); 24 System.out.println("服务器:"+serverStr); 25 } 26 keyReader.close(); 27 // 4. 关闭资源。 28 socket.close(); 29 } 30 } 31 import java.io.BufferedReader; 32 import java.io.BufferedWriter; 33 import java.io.IOException; 34 import java.io.InputStreamReader; 35 import java.io.OutputStreamWriter; 36 import java.net.ServerSocket; 37 import java.net.Socket; 38 39 //服务器端 40 public class TCPChatServer { 41 public static void main(String[] args) throws IOException { 42 //1. 建立tcp服务端 的服务。 43 ServerSocket serverSocket = new ServerSocket(9090); 44 //2. 接受客户端的连接产生一个Socket. 45 Socket socket = serverSocket.accept(); 46 //获取对应的流 47 BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 48 BufferedWriter socketWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 49 BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in)); 50 String line = null; 51 while ((line = socketReader.readLine()) != null) { 52 //读写 53 System.out.println("客户端:"+line); 54 socketWriter.write(keyReader.readLine()+"\\r\\n"); 55 socketWriter.flush(); 56 } 57 //关闭 58 keyReader.close(); 59 serverSocket.close(); 60 } 61 }
2、多线程下载图片
1 //下载图片的客户端 2 public class ImageClient { 3 4 public static void main(String[] args) throws Exception{ 5 //建立tcp的服务 6 Socket socket = new Socket(InetAddress.getLocalHost(),9090); 7 //获取socket的输入流对象 8 InputStream inputStream = socket.getInputStream(); 9 //获取文件的输出流对象 10 FileOutputStream fileOutputStream = new FileOutputStream("F:\\\\3.jpg"); 11 //边读边写 12 byte[] buf = new byte[1024]; 13 int length = 0 ; 14 while((length = inputStream.read(buf))!=-1){ 15 fileOutputStream.write(buf,0,length); 16 } 17 //关闭资源 18 fileOutputStream.close(); 19 socket.close(); 20 21 } 22 23 } 24 //下载图片服务端 25 public class ImageServer extends Thread { 26 27 Socket socket ; 28 29 //使用该集合是用于存储ip地址的。 30 static HashSet<String> ips = new HashSet<String>(); 31 32 public ImageServer(Socket socket) { 33 this.socket = socket; 34 } 35 36 @Override 37 public void run() { 38 try { 39 //获取到socket输出流对象 40 OutputStream outputStream = socket.getOutputStream(); 41 //获取图片的输入流对象 42 FileInputStream fileInputStream = new FileInputStream("F:\\\\美女\\\\3.jpg"); 43 //读取图片数据,把数据写出 44 byte[] buf = new byte[1024]; 45 int length = 0 ; 46 while((length = fileInputStream.read(buf))!=-1){ 47 48 outputStream.write(buf,0,length); 49 } 50 String ip = socket.getInetAddress().getHostAddress(); // socket.getInetAddress() 获取对方的IP地址 51 if(ips.add(ip)){ 52 System.out.println("恭喜"+ip+"同学成功下载,当前下载的人数是:"+ ips.size()); 53 } 54 55 56 57 //关闭资源 58 fileInputStream.close(); 59 socket.close(); 60 }catch (IOException e) { 61 62 } 63 } 64 65 66 public static void main(String[] args) throws IOException { 67 //建立tcp的服务 ,并且要监听一个端口 68 ServerSocket serverSocket = new ServerSocket(9090); 69 while(true){ 70 //接受用户的链接。 71 Socket socket = serverSocket.accept(); 72 new ImageServer(socket).start(); 73 74 } 75 } 76 77 }
3、多线程登录注册
1 //登录客户端 2 public class LoginClinet { 3 4 public static void main(String[] args) throws IOException { 5 Socket socket = new Socket(InetAddress.getLocalHost(),9090); 6 //获取socket的输出流对象 7 OutputStreamWriter socketOut = new OutputStreamWriter(socket.getOutputStream()); 8 9 //获取到socket的输入流对象 10 BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 11 12 //获取到键盘的输入流对象 13 BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in)); 14 while(true){ 15 System.out.println("请选择功能: A(登陆) B(注册)"); 16 String option = keyReader.readLine(); 17 if("a".equalsIgnoreCase(option)){ 18 getInfo(socketOut, keyReader, option); 19 //读取服务器反馈的信息 20 String line = socketReader.readLine(); 21 System.out.println(line); 22 }else if("b".equalsIgnoreCase(option)){ 23 getInfo(socketOut, keyReader, option); 24 //读取服务器反馈的信息 25 String line = socketReader.readLine(); 26 System.out.println(line); 27 } 28 29 } 30 31 32 } 33 34 public static void getInfo(OutputStreamWriter socketOut,BufferedReader keyReader, String option) 35 throws IOException { 36 System.out.println("请输入用户名:"); 37 String userName = keyReader.readLine(); 38 System.out.println("请输入密码:"); 39 String password = keyReader.readLine(); 40 String info = option +" "+userName+" "+password+"\\r\\n"; 41 socketOut.write(info); 42 socketOut.flush(); 43 } 44 45 } 46 //登录服务端 47 public class LoginServer extends Thread { 48 49 Socket socket; 50 51 static File file = new File("E:\\\\users.properties"); 52 53 public LoginServer(Socket socket) { 54 this.socket = socket; 55 } 56 57 static { 58 try { 59 if (!file.exists()) { 60 file.createNewFile(); 61 } 62 } catch (IOException e) { 63 e.printStackTrace(); 64 } 65 66 } 67 68 @Override 69 public void run() { 70 while(true){ 71 System.out.println(Thread.currentThread()); 72 try { 73 // 获取socket的输入流对象 74 BufferedReader bufferedReader = new BufferedReader( 75 new InputStreamReader(socket.getInputStream())); 76 // 获取socket的输出流对象 77 OutputStreamWriter socketOut = new OutputStreamWriter( 78 socket.getOutputStream()); 79 80 // 读取客户端输入的信息 81 String info = bufferedReader.readLine(); 82 String[] datas = info.split(" "); 83 // 获取到用户 的选择功能 84 String option = datas[0]; 85 // 注册 86 String userName = datas[1]; 87 88 String password = datas[2]; 89 90 if ("a".equalsIgnoreCase(option)) { 91 // 登陆 92 Properties properties = new Properties(); 93 // 加载配置文件 94 properties.load(new FileReader(file)); 95 if (properties.containsKey(userName)) { 96 String tempPass = properties.getProperty(userName); 97 if (password.equals(tempPass)) { 98 socketOut.write("欢迎" + userName + "登陆成功\\r\\n"); 99 100 } else { 101 socketOut.write("密码错误\\r\\n"); 102 } 103 104 } else { 105 socketOut.write("用户名不存在,请重新输入...\\r\\n"); 106 } 107 108 socketOut.flush(); 109 110 } else if ("b".equalsIgnoreCase(option)) { 111 112 // 创建一个配置文件类 113 Properties properties = new Properties(); 114 //加载原来的配置文件 115 properties.load(new FileReader(file)); 116 if (!properties.containsKey(userName)) { 117 // 不存在该用户名 118 properties.setProperty(userName, password); 119 // 生成一个配置文件 120 properties.store(new FileWriter(file), "users"); 121 socketOut.write("注册成功..\\r\\n"); 122 } else { 123 // 存在用户名 124 socketOut.write("用户名已经被注册,请重新输入\\r\\n"); 125 } 126 socketOut.flush(); 127 } 128 } catch (Exception e) { 129 e.printStackTrace(); 130 } 131 } 以上是关于网络编程的主要内容,如果未能解决你的问题,请参考以下文章VSCode自定义代码片段14——Vue的axios网络请求封装
VSCode自定义代码片段14——Vue的axios网络请求封装