欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java网络编程以及通信的项目研究

程序员文章站 2023-02-17 08:14:48
网络编程...

什么是网络编程

就是使用编程语言进行多态计算机之间的通信

网络编程的三大要素

  • IP地址:网络内的每一台计算机的唯一标识,通过IP找到指定的计算机
  • 端口:用于标识进程的逻辑地址,通过端口找到指定的进程
  • 协议:定义通信规则,符合协议则可以通信,不符合不可以通信
    通俗点来说,就是,我要和小王说话,首先我要找到小王的地址(相当于通过IP找到指定的计算机);之后我要和小王说话,小王用耳朵听我说(相当于使用端口接收);而我们对化需要使用双方都可以听懂的普通话(这就是协议的作用)
    我们在命令提示符内,输入 cmd 进入,输入 ipconfig找到自己的ip地址
    IPv4地址对应的就是网络ID
    127.0.0.1 用于本机测试吗,是本机回环地址
    255.255.255.0 是当前子网,一般用于当前子网广播信息

Socket

套接字,是计算机之间通信的一种约定或者一种方式,通过Socket这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。
通俗来说,如果你想给远方的朋友写一封信,如何写信,将信打包,属于应用层。信怎么写,怎么打包完全由我们自己做主
当我们将信放入邮筒时,邮筒的投信口就是套接字

TCP协议的数据传递细节

TCP通信原理

服务器创建ServerSocket,在指定的端口监听并处理请求,客户端创建Socket,向服务器发送请求。

流程示意图:

Socket是客户端 ServerSocket是服务器端

java网络编程以及通信的项目研究
java网络编程以及通信的项目研究

UDP协议数据传递细节

  • UDP协议不需要利用IO流实现数据的传输
  • 每个数据发送单元被统一封装为数据包的方式,发送方将数据包发送到网络内,数据包在网络内去寻找他的目的地。
  • DatagramSocket:用于发送或者接收数据包
  • DatagramPacket:数据包
    java网络编程以及通信的项目研究

TCP的接收方和发送方是固定的,而我们从上面这个图可以看出,UDP接收方和发送方并不固定,所以UDP统一使用DatagramSocket去表示双方内的某一方

流程示意图:

java网络编程以及通信的项目研究

对InetAddress类和InetSocketAddress类的实践

InetAddress类

这种类用于IP套接字地址(IP地址+ 端口号),用于socket通信

InetAddress类常用的方法

java网络编程以及通信的项目研究
实例代码:

package net;

import java.net.InetAddress;

public class TestInetAddress {
    public static void main(String[] args) throws Exception {
        //1. 获取InetAddress的方式
        InetAddress ia =   InetAddress.getLocalHost();
        System.out.println("获取主机的ip地址"+ia.getHostAddress());
        System.out.println("获取主机名称:"+ia.getHostName());

        //2.根据域名去获取InetAddress对象
        InetAddress ia2 = InetAddress.getByName("www.baidu.com");
        System.out.println("百度服务器的IP地址:"+ia2.getHostAddress());
        System.out.println("主机名称:"+ia2.getHostName());

        //3.根据IP地址获取一个InetAddress对象
        //这里返回主机名称时,返回的是主机的IP而不是主机的域名
        //这是因为IP地址不存在或者主机服务器不允许进行一个主机IP地址的映射,这就会返回一个IP地址
        InetAddress ia3 = InetAddress.getByName("61.135.253.15");
        System.out.println("服务器主机IP:"+ia3.getHostAddress());
        System.out.println("主机名称:"+ia3.getHostName());
    }
}

java网络编程以及通信的项目研究

package net;

import java.net.InetAddress;
import java.net.InetSocketAddress;

public class TestInetSocketAddress {
    public static void main(String[] args) throws Exception {
        //创建对象
        InetSocketAddress tsa = new InetSocketAddress("localhost",9999);
        InetSocketAddress tsa2 = new InetSocketAddress("127.0.0.1",9999);
        InetSocketAddress tsa3 = new InetSocketAddress("192.168.86.100",9999);

        InetAddress ia = InetAddress.getByName("localhost");
        InetSocketAddress tsa4 = new InetSocketAddress(ia,9999);
        System.out.println("主机名称:"+tsa4.getHostName());
        System.out.println("主机IP地址:"+tsa4.getAddress());
    }
}

java网络编程以及通信的项目研究

URL类

URL是统一资源定位符,由四部分组成:协议,存放资源的主机域名,端口号,资源文件名
如:http://www.baidu.com:80/index.html#aa?name=bb
#aa是一个锚点
URL 内 ?后的是传递的参数
URL类实践:

package net;

import java.net.MalformedURLException;
import java.net.URL;

public class TestURL {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://www.baidu.com:80/index.html#aa?username=bjsxt&pwd=bjsxt");
        System.out.println("协议名称:"+url.getProtocol());
        System.out.println("主进程:"+url.getHost());
        System.out.println("端口号:"+url.getPort());
        System.out.println("获取资源路径:"+url.getFile());
        System.out.println("获取默认端口号:"+url.getDefaultPort());
        System.out.println("获中国URL的路径部分:"+url.getPath());
    }
}

java网络编程以及通信的项目研究

package net;

import java.io.*;
import java.net.URL;

public class TestURL2 {
    public static void main(String[] args) throws IOException {
        /**
         * 网络爬虫
         * 1. 从网络内获取资源
         * 2. 存储到本地
         */
        //1.创建URL对象
        URL url = new URL("http://www.baidu.com");
        //2.获取字节输入流
        InputStream is = url.openStream();
        //3.缓冲流
        BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));
        //4. 存储到本地
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("index.html")));
        //5.边读边写
        String line = null;
        while ((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        //6. 关闭流
        bw.close();
        br.close();

    }
}

在运行之后,会增加一个从百度网址爬取到的内容,存放在了这个index.html页面内。
java网络编程以及通信的项目研究

实现基于TCp协议的Socket编程

单向通信实现

字节流

客户端向服务器端发送的是字节,第二步发送的是字符串
需要知道,服务器端和客户端分别在两个项目的不同包下,以模拟两个电脑之间进行数据传递
先编写服务器端

package net.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 这是服务器端端的应用程序代码
 */
public class Test {
    public static void main(String[] args) throws IOException {
        System.out.println("---------服务器端启动----------");
        //1.创建ServerSocket对象
        ServerSocket server = new ServerSocket(9999);
        //2.监听是否有客户端来请求
        Socket client = server.accept();
        //3.获取输入流
        InputStream is = client.getInputStream();
        System.out.println((char)is.read());
        //4.获取输出流
        //我们想向客户端发送“收到了” 需要获取输出流
        OutputStream os =  client.getOutputStream();
        os.write("服务器端收到了".getBytes());
        //5.一次通信结束,关闭流 关闭Socket
        if (os!=null){
            os.close();
        }
        if (is!=null){
            is.close();
        }
        if (client!=null){
            client.close();
        }
    }
}

再编写客户端

package client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 客户端
 */
public class Test {
    public static void main(String[] args) throws IOException {
        System.out.println("------客户端启动---------");
        //1.创建我们的Socket对象
        Socket client  =new Socket("192.168.86.100",9999);
        //2.获取输出流
        OutputStream os = client.getOutputStream();
        //服务器端是接收一个字节,那我们在客户端就应该去发送一个字节
        os.write('a');
        //3.获取输入流
        InputStream is = client.getInputStream();
        byte[] buf = new byte[1024];//中转站
        int len = 0;    //读到的字节的个数
        while ((len=is.read(buf))!=-1){
            System.out.println(new String(buf,0,len));
        }
        //4.关闭流
        if (is!=null){
            is.close();
        }
        if (os!=null){
            os.close();
        }
        if (client!=null){
            client.close();
        }
    }
}

我们先启动服务器端
java网络编程以及通信的项目研究
再启动客户端
java网络编程以及通信的项目研究

这样,我们就实现了客户端向服务器端发送一个字节

数据流(可以发送多个字节)

服务器端:

package net.server;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 这是服务器端的应用程序代码
 */
public class Test2 {
    public static void main(String[] args) throws IOException {
        System.out.println("---------数据流版的服务器端启动----------");
        //1.创建ServerSocket对象
        ServerSocket server = new ServerSocket(9999);
        //2.监听是否有客户端来请求
        Socket client = server.accept();
        //3.获取输入流
        DataInputStream dis = new DataInputStream(client.getInputStream());
        System.out.println(dis.readUTF());
        //4.获取输出流
        //我们想向客户端发送“收到了” 需要获取输出流
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());
        dos.writeUTF("服务器端收到了");
        //5.一次通信结束,关闭流 关闭Socket
        if (dos!=null){
            dos.close();
        }
        if (dis!=null){
            dis.close();
        }
        if (client!=null){
            client.close();
        }
    }
}

客户端:

package client;

import java.io.*;
import java.net.Socket;

/**
 * 客户端
 */
public class Test2 {
    public static void main(String[] args) throws IOException {
        System.out.println("------数据流版的客户端启动---------");
        //1.创建我们的Socket对象
        Socket client  =new Socket("127.0.0.1",9999);
        //2.获取输出流
        DataOutputStream dos = new DataOutputStream(client.getOutputStream());
        dos.writeUTF("helloWorld");
        //3.获取输入流
        DataInputStream dis = new DataInputStream(client.getInputStream());
        System.out.println(dis.readUTF());
        //4.关闭流
        if (dis!=null){
            dis.close();
        }
        if (dos!=null){
            dos.close();
        }
        if (client!=null){
            client.close();
        }
    }
}

我们先启动服务器端,然后启动客户端,结果如下:
java网络编程以及通信的项目研究

双向通信实现

服务器端和客户端不可以在同一个项目下,且,双向通信的实现前提,两个类所在的包结构和包名必须一致
服务器端:

package net.entity;

import net.thread.ServerThread;

import java.io.DataOutputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("服务器端启动");
        //1. 创建ServerSocket对象
        ServerSocket server = new ServerSocket(9999);
        while (true){
            Socket socket = server.accept();
            //创建线程类的对象,并启动线程
            ServerThread st = new ServerThread(socket);
            //启动线程
            new Thread(st).start();
        }

    }
}

客户端:

package net.entity;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        System.out.println("客户端启动");
        //1. 创建Socket对象,用于连接服务器
        Socket client = new Socket("127.0.0.1",9999);
        //2. 创建输出流(也就是对象流)
        ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
        //3. 创建User对象
            //调用获取用户信息的getUser()
        User u =  getUser();//new User("aaa","aaa");
        //4. User对象发送到服务器
        oos.writeObject(u);
        //5. 获取输入流(使用数据流激进行获取)
        DataInputStream dis = new DataInputStream(client.getInputStream());
        System.out.println(dis.readUTF());
        //6. 关闭流
        if (oos!=null){
            oos.close();
        }
        if (dis!=null){
            dis.close();
        }
        if (client!=null){
            client.close();
        }
    }
    //获取用户对象的方法
    public static User getUser(){
        Scanner input = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String userName = input.next();
        System.out.println("请输入密码:");
        String passWord = input.next();
        //封装为User对象
        return new User(userName,passWord);
    }
}

运行结果:
java网络编程以及通信的项目研究
以上,为双向通信的实验
在实现过程内,有什么疑问,原理上的难点,请留言,我会尽快回复

本文地址:https://blog.csdn.net/qq_43545801/article/details/109552092

相关标签: 项目 java