网络编程

网络编程

网络编程主要用于解决计算机与计算机(手机、平板..)之间的数据传输问题。

网络编程和网页编程的区别
网络编程: 不需要基于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 }
View Code

TCP网络编程涉及到的类:Socket和ServerSocket

Socket:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。

常用方法

1、构造方法

Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号。

2、普通方法

OutputStream getOutputStream() 返回此套接字的输出流。

InputStream getInputStream() 返回此套接字的输入流。

ServerSocket:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

常用方法:

1、构造方法

ServerSocket(int port) 创建绑定到特定端口的服务器套接字。

2、普通方法

Socket accept()侦听并接受到此套接字的连接。

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+"
");
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()+"
");
55             socketWriter.flush();
56         }
57         //关闭
58         keyReader.close();
59         serverSocket.close();
60     }
61 }
View Code

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 }
View Code

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+"
";
 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 + "登陆成功
");
 99     
100                         } else {
101                             socketOut.write("密码错误
");
102                         }
103     
104                     } else {
105                         socketOut.write("用户名不存在,请重新输入...
");
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("注册成功..
");
122                     } else {
123                         // 存在用户名
124                         socketOut.write("用户名已经被注册,请重新输入
");
125                     }
126                     socketOut.flush();
127                 }
128             } catch (Exception e) {
129                 e.printStackTrace();
130             }
131         }
132 
133     }
134 
135     public static void main(String[] args) throws IOException {
136         ServerSocket serverSocket = new ServerSocket(9090);
137         while (true) {
138             Socket socket = serverSocket.accept();
139             new LoginServer(socket).start();
140         }
141 
142     }
143 
144 }
View Code
原文地址:https://www.cnblogs.com/nicker/p/6257891.html