随笔都是学习笔记
随笔仅供参考,为避免笔记中可能出现的错误误导他人,请勿转载。

简介:

网络编程就是指多台主机之间的数据通讯操作。

网络的核心定义:有两台以上的电脑就称为网络。

如何生产更多的电脑并将其进行连接。

网络连接的目的不仅仅是进行电脑的串联,更多的是为了进行彼此之间的数据通讯,包括现在的网络游戏实质上还是网络通讯的问题,而在通讯的实现上就产生了一系列处理的协议:IP、TCP、UDP等,所谓的网络编程实际上实现的就是数据通讯操作,只是这个通讯操作需要分为客户端和服务器端。

那么针对于网络程序的开发就有了两种模型:

  - C/S(Client/Server:客户端、服务器端):

要开发出两套程序,一套程序为客户端,一套为服务器端,如果服务器端发生了改变之后客户端也要进行更新处理,这种开发可以由开发者自定义传输协议,并且使用一些私密的端口所以安全性比较高,但是开发与维护成本比较高(两套程序,变一则都变);

  - B/S(Browse/Server:浏览器、服务器端):

只开发服务器端的程序,而后利用浏览器作为客户端进行访问,这种开发与维护的成本较低(只有一套程序),但是由于使用的公共的HTTP协议,并且使用的公共的80端口,所以其安全性较低,现在的开发基本上以“B/S”结构为主;

 

 

C/S程序模型(TCP[可靠的数据连接]、UDP[不可靠的数据连接]):

 

TCP程序的基本实现:

TCP的程序开发是网络程序最基本的开发模型,其核心是使用两个类实现数据的交互处理:ServerSocket(服务器端)、Socket(客户端)

ServerSocket设置服务器连接端口,Socket需要指明服务器的地址与端口。

Echo模型

客户端有接收和输出操作,服务器端也有接收和输出操作。

实现一个Echo模型操作:

服务器端: 

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class serverSocket {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(9999);    // 设置服务器端的监听端口
        System.out.println("等待客户端连接.......");
        Socket client = server.accept();    // 有客户端的连接
        // 首先需要先接收客户端发送的信息然后将信息发送回客户端
        Scanner sc = new Scanner(client.getInputStream());    // 客户端输入流
        sc.useDelimiter("\n");    // 等待输入
        PrintStream out = new PrintStream(client.getOutputStream());    // 客户端输出流
        boolean flag = true;
        while(flag) {
            if(sc.hasNext()) {    // 如果有数据
                String val = sc.next();    // 接收发送的数据
                if("byebye".equalsIgnoreCase(val)) {
                    out.println("再见!");
                    flag = false;
                }else {
                    out.println("【Ehco】" + val);
                }
            }
        }
        sc.close();
        out.close();
        client.close();
        server.close();
        
    }
}

客户端:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class socketClient {
    private static final BufferedReader KEY_INPUT = new BufferedReader(new InputStreamReader(System.in));
    public static void main(String[] args) throws Exception {
        Socket client = new Socket("localhost",9999);    // 定义服务器端的连接信息
        // 现在客户端需要有输入与输出的操作
        Scanner sc = new Scanner(client.getInputStream());    // 接收服务器端的输入内容
        sc.useDelimiter("\n");
        PrintStream out = new PrintStream(client.getOutputStream());    // 向服务器端输出内容
        boolean flag = true;
        while (flag) {
            String input = getString("请输入发送的内容:").trim();
            out.println(input);    // 加换行
            if(sc.hasNext()) {    // 服务器端回应
                System.out.println(sc.next());
            }
            if("byebye".equalsIgnoreCase(input)) {
                flag = false;
            }
        }
        sc.close();
        out.close();
        client.close();
    }
    public static String getString(String prompt) throws Exception{
        System.out.print(prompt);
        String str = KEY_INPUT.readLine();
        return str;
    }
}输出结果:


以上就是最基本的客户端与服务器端的操作实现。

 

多线程与网络编程:

 

上面的程序虽然实现了网络程序的开发,但是整个程序只能为一个线程提供Echo服务。

如果已经有一人连接了服务器,而还有其余的人想要连接服务器,那么就需要等待连接,只有前面的连接断开才能进行下一个连接,但是因为上面程序的客户端结束后服务器端会一起结束,所以导致了从开始到结束都只能为一个人提供服务。

现在就需要解决这种缺陷,就是将每一个访问服务器的客户端都使用线程对象处理,即:服务器上启动多个线程,每一个线程为每一个服务器端实现Echo服务支持。

 

修改服务器端程序:

package Demo_3_19_Echo模型;

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class serverSocket {
    private static class ClientThread implements Runnable{
        private Socket client = null;    // 描述每一个不同的客户端
        private Scanner sc = null;    
        PrintStream out = null;
        public boolean flag = true;
        public ClientThread(Socket client) throws Exception{
            this.client = client;
            this.sc = new Scanner(client.getInputStream());    // 客户端输入流
            this.sc.useDelimiter("\n");    // 等待输入
            this.out = new PrintStream(client.getOutputStream());    // 客户端输出流
        }
        @Override
        public void run() {
            while(this.flag) {
                if(this.sc.hasNext()) {    // 如果有数据
                    String val = this.sc.next();    // 接收发送的数据
                    if("byebye".equalsIgnoreCase(val)) {
                        out.println("再见!");
                        this.flag = false;
                    }else {
                        out.println("【Ehco】" + val);
                    }
                }
            }
            try {
                sc.close();
                out.close();
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(9999);    // 设置服务器端的监听端口
        System.out.println("等待客户端连接.......");
        boolean flag = true;    // 循环标记
        while(flag) {    // 循环接收客户端
            Socket client = server.accept();    // 有客户端的连接
            new Thread(new ClientThread(client)).start();    // 每接收一个客户端就使用线程对象包装
        }
        server.close();
    }
}

 

上面的代码启动了一个服务器端和两个客户端,可以发现两个客户端可以同时进行访问。

 

UDP(基于网络报)网络程序实现:

实现UDP的网络程序需要两个类:DatagramPacket(包含的数据内容)、DatagrmSocket(网络的发送与接收);

数据报就像发送的短消息一样,客户端是否接收到与发送者无关。

 

UDP服务器端:

package Demo_3_20_UDPServer;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPServer {
    public static void main(String[] args) throws Exception{
        DatagramSocket server = new DatagramSocket(9000);    // 监听端口为9000       
        String str = "www.baidu.com";     // 要发送的消息
        DatagramPacket pac = new DatagramPacket(str.getBytes(),0,str.length(),InetAddress.getByName("localhost"),9999);    // 发送数据,连接到9999端口
        server.send(pac);    // 发送消息
        System.out.println("消息发送完毕.......");
    }
}

客户端:

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPClient {
    public static void main(String[] args) throws Exception {
        DatagramSocket client = new DatagramSocket(9999);    // 连接到9999端口
        byte[] data = new byte[1024];    // 接收消息
        DatagramPacket pac = new DatagramPacket(data,data.length);    // 接收数据
        System.out.println("客户端等待接收消息.......");
        client.receive(pac);    // 接收消息,所有的消息都在data字节数组之中
        System.out.println("接收到的消息内容为:" + new String(data,0,pac.getLength()));
        client.close();
    }
}

输出结果:

 

 

先启动客户端,然后启动服务器端就能发送消息过去;

UDP发送的数据是不可靠的,但是TCP需要保证可靠的连接,所以需要的服务器的资源更多。

 

posted on 2022-03-19 23:23  时间完全不够用啊  阅读(174)  评论(0编辑  收藏  举报