JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用


GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例,我们暂时不讲了,我们直接来重点吧,关于JAVA的网络请求是怎么实现的?当然是HTTP协议,但是不可否认,他的概念和思想都是我们必须去涉及的,包括后面的tcp和socket等,好吧,我们开车吧!

一.JAVA网络请求概述

关于JAVA的网络请求,我们大致的可以分为以下几个分类

  • 网络模式

    • OSI
    • TCP/IP
  • 网络通讯
    • IP地址
    • 端口号
    • 传输协议

拿这些都是干嘛的呢?我们接下来都会讲到

首先我们应该思考的是他们通信的一个过程的步骤

  • 1.找到对方IP
  • 2.数据发送到指定应用程序上,为了识别,就有了端口的概念
  • 3.定义通信协议(也就是后来的传输协议)国际协议/TCP/IP
  • 4.三要素:IP,端口,协议

OK,那我们就研究下网络模型,OSI和TCP/IP的区别

其实理解起来也不难,我们看一下他的逻辑结构就知道了

  • OSI

    • 应用层
    • 表示层
    • 会话层
    • 传输层
    • 网络层
    • 数据链路层
    • 物理层
  • TCP/IP

    • 应用层
    • 传输层
    • 网络层
    • 主机-网络层

应用层,我们就在这里玩,TCP封装了就比较好用,他们都有使用规则,而我们常用的大概就是HTTP协议了

二.IP地址

通讯要素大致的就是这些,我们来说一下我们耳熟能详的IP地址,他是什么概念呢?

  • IP地址

    • 网络中设备的标识
    • 可用主机名
    • 本地回环地址:127.0.0.1,主机名:location
  • 端口号

    • 用于标识进程的逻辑地址,不同进程的标识
    • 有效端口:0-65535,其中0-1024系统使用或者保留,我们熟知的8080
  • 通讯协议

    • 通讯的规则
    • 常见的TCP,UDP

我们可用用代码获得哦,先看API文档,会发现JAVA给我们提供了一个类InetAddress

我们可用直接去用代码使用

try {
    InetAddress localHost = InetAddress.getLocalHost();
    System.out.println(localHost.toString());
} catch (UnknownHostException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

可以得到

得到的本机的主机名和IP地址

当然,你要单独获取也是没问题的

        try {
            InetAddress localHost = InetAddress.getLocalHost();
            String hostAddress = localHost.getHostAddress();
            String hostName = localHost.getHostName();
            System.out.println(localHost.toString());
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

三.TCP/UDP通讯协议概述

端口我们没什么可说的,我们直接说通讯协议,目前常见的就是TCP/UDP了,我们先来简单的说下他们的概念

  • TCP

    • 建立连接,形成传输数据的通道
    • 在连接中进行大数据量传输
    • 通过三次握手完成连接,是可靠协议
    • 必须建立连接,效率稍微低点
  • UDP

    • 将数据及源和目的封装在数据包中,不需要建立连接
    • 每个数据包的大小限制在64K内
    • 因无连接,是不可靠协议
    • 不需要建立连接,速度快

这些这么多,java肯定会给我们封装对象的,这个是毋庸置疑的,那我们接着往下看

四.Socket

Socket就厉害了,我们先来看看他的概念

  • Socket就是为网络服务提供的一种机制
  • 通信的两端都有socket
  • 网络通信其实就是socket通信
  • 数据在两个socket通过IO传输

我们现在先说概念,后期再实战

五.UDP传输

UDP传输的socket服务该怎么建立?

  • DatagramSocket和DatagramPacket
  • 建立发送端和接收端
  • 建立数据包
  • 调用socket的发送和接收方法
  • 关闭socket

客户端和服务端是两个单独的服务,我们可用来用代码讲解下,用到的就是DatagramSocket和DatagramPacket

所以这里应该是有两个,一个传输端,一个接收端

传输端


/**
 * 需求: 通过UDP传输方式将一段文字数据发送出去
 * 思路:
 * 1.建立UDP的socket服务
 * 2.建立数据包
 * 3.发送数据
 * 4.关闭资源
 *
 * @author LGL
 *
 */
public class UdpSend {
    public static void main(String[] args) {
        try {
            // 1.建立UDP的socket服务,通过DatagramSocket对象
            DatagramSocket dSocket = new DatagramSocket();
            // 2.确定数据,封装成数据包
            byte[] data = "udp".getBytes();
            DatagramPacket dp = new DatagramPacket(data, data.length,
                    InetAddress.getByName("192.168.1.102"), 8080);
            // 3.发送数据
            dSocket.send(dp);
            // 4.关闭资源
            dSocket.close();
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

接收端

/**
 * 需求:接收指定端口发送过来的数据
 * 思路:
 * 1.定义socket服务
 * 2.定义数据包,存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息
 * 3.通过socket的receive方法收到的数据存储到数据包中
 * 4.将这些不同的数据取出,打印
 * 5.关闭资源
 *
 * @author LGL
 *
 */
class UdpRece {
    public static void main(String[] args) {
        try {
            // 1.创建服务,建立端点
            DatagramSocket dSocket = new DatagramSocket(8080);
            // 2.定义数据包,存储数据
            byte[] buf = new byte[1024];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            // 3.存储
            dSocket.receive(dp);
            // 4.获取其中的数据
            String ip = dp.getAddress().getHostAddress();
            String data = new String(dp.getData(), 0, dp.getLength());
            int port = dp.getPort();
            System.out.println(ip+":" + data + ":" + port);
            //5.关闭资源
            dSocket.close();
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这样就可以通信了

六.多线程UDP聊天应用

既然上面有模有样的写出来了,那我们可以动手写一个应用了,我们继续来看,我不开多个进程,我写一个进程,两个线程来实现聊天

package com.lgl.hellojava;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * 编写一个聊天应用程序 有收数据和发数据的部分,所以用到多线程的技术,一个接一个发 收和发的动作不一致,所以有两个Runnable
 *
 * @author LGL
 *
 */
public class UdpSpeak {

    public static void main(String[] args) {

        try {
            DatagramSocket sendSocket = new DatagramSocket();
            DatagramSocket receSocket = new DatagramSocket(10000);

            new Thread(new send(sendSocket)).start();
            new Thread(new rece(receSocket)).start();

        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

/**
 * 发送
 *
 * @author LGL
 *
 */
class send implements Runnable {

    private DatagramSocket socket;

    public send(DatagramSocket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            BufferedReader bufr = new BufferedReader(new InputStreamReader(
                    System.in));
            String line = null;
            while ((line = bufr.readLine()) != null) {
                if ("close".equals(line)) {
                    break;
                }
                byte[] buf = line.getBytes();
                DatagramPacket dp = new DatagramPacket(buf, buf.length,
                        InetAddress.getByName("192.168.1.102"), 10000);
                socket.send(dp);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

/**
 * 接收
 *
 * @author LGL
 *
 */
class rece implements Runnable {

    private DatagramSocket socket;

    public rece(DatagramSocket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        while (true) {
            try {
                byte[] buf = new byte[1024];
                DatagramPacket dp = new DatagramPacket(buf, buf.length);
                socket.receive(dp);

                String ip = dp.getAddress().getHostAddress();
                String data = new String(dp.getData(), 0, dp.getLength());
                int port = dp.getPort();
                System.out.println(ip + ":" + data + ":" + port);

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

OK,搞定,其实主要还是要了解他的思想,编码什么的不重要的

好了,本篇主要是以UDP和概念为起点,而且UDP用的较少,我们一般不是常接触,真正要用的是TCP,所以会重点掌握,那本篇,我们先到这里就好了

JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用的更多相关文章

  1. 菜鸡的Java笔记 第三十二 - java 静态导入的实现

    静态导入的实现        为了理解静态导入的操作产生的动机,下面通过一个具体的代码来观察        范例:现在有一个 Import 的类,这个类中的方法全部都是 static 方法 packa ...

  2. JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口

    JAVA之旅(十二)--Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口 开始挑战一些难度了,线程和I/O方面的操作了,继续坚持 一. ...

  3. Java学习笔记【十二、网络编程】

    原计划的学习结束时间是3月4日,目前看来已经延迟了,距离低标还差一些,多方面原因,也不找借口,利用周末赶赶进度,争取本周末把低标完成吧! 参考: http://www.runoob.com/java/ ...

  4. Python之路(第三十二篇) 网络编程:udp套接字、简单文件传输

    一.UDP套接字 服务端 # udp是无链接的,先启动哪一端都不会报错 # udp没有链接,与tcp相比没有链接循环,只有通讯循环 server = socket.socket(socket.AF_I ...

  5. Java从零开始学三十二(正则表达式)

    一.为什么要有正则 正则表达式可以方便的对数据进行匹配,可以执行更加复杂的字符串验证.拆份.替换功能. 例如:现在要求判断一个字符串是否由数字组成,则可以有以下的两种做法: 不使用正则完成 使用正则完 ...

  6. Java基础(三十二)JDBC(2)连接数据库

    一.连接数据库的过程 连接数据库的过程:加载数据库驱动程序,不过只需在第一次访问数据库时加载一次,然后在每次访问数据库时创建一个Connection实例,然后执行操作数据库的SQL语句,并返回执行结果 ...

  7. Java开发学习(三十二)----Maven多环境配置切换与跳过测试的三种方式

    一.多环境开发 我们平常都是在自己的开发环境进行开发, 当开发完成后,需要把开发的功能部署到测试环境供测试人员进行测试使用, 等测试人员测试通过后,我们会将项目部署到生成环境上线使用. 这个时候就有一 ...

  8. JAVA学习第三十二课(经常使用对象API)- 基本数据类型对象包装类

    将基本数据类型(8种:int..)封装成对象的优点就是能够在对象中封装很多其它的功能和方法来操控该数据 常见的操作就是:用于基本数据类型与字符串之间的转换 基本数据类型对象包装类一般用于基本类型和字符 ...

  9. java 面向对象(三十二):泛型一 泛型的理解

    1.泛型的概念所谓泛型,就是允许在定义类.接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型.这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量.创建对象时确定 ...

随机推荐

  1. SAC E#1 - 一道难题 Tree

    题目背景 冴月麟和魏潇承是好朋友. 题目描述 冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了.任何人都无法进入真实的幻想乡了,但是她给前来救她的魏潇承留了一个线索. 她设置了一棵树( ...

  2. ●BZOJ 4566 [Haoi2016]找相同字符

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4566题解: 广义后缀自动机 对两个串同时建立一个广义后缀自动机. 同时统计出每个状态对两个串 ...

  3. UVA11404:Palindromic Subsequence

    回文子串dp,最小字典序的话需要记录一下,注意是string型的,不能只记录一个字符,因为可能出现相等的情况 #include<cstdio> #include<cstdlib> ...

  4. ●HDU 2871 Memory Control(Splay)

    ●赘述题目 四种操作: ○Reset:将整个内存序列清空. ○New a:在尽量靠左的位置新建一个长度为a的内存块,并输出改内存块起始位置.(各个内存块即使相邻也不会合并..) ○Free a:将a点 ...

  5. 2015 多校联赛 ——HDU5323(搜索)

    Solve this interesting problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  6. SqlServer 跨网段跨服务器复制

    注意:被同步的表必须有主键,否则无法同步.对数据库进行操作时需要登录服务器,在服务器本地进行操作,远程对数据库进行操作不能完成所有的步骤 准备工作: 1.将发布数据库完整备份到订阅服务器上,并在订阅服 ...

  7. 存储单位的换算(KB, MB, GB)

    关于存储单位的换算,大家一般会想到下面的换算方法. 1GB=1024MB 1MB=1024KB 1kb=1024字节 但实际生活中,这种换算方法并不准确. 例如在商家生产销售的硬盘, U盘中就不是这样 ...

  8. 3.2 2-dim Vector Initialization

    声明3行4列的数组 const int m = 3, n = 4; vector<vector<int> > A(m); // 3 rows for(int i = 0; i ...

  9. page1

    1.1 常用的客户端技术:HTML. CSS. 客户端脚本技术 1.2 常用的服务器端技术:CGI .ASP .PHP (一种开发动态网页技术).ASP.NET(是一种建立动态web应用程序的技术,是 ...

  10. Node.js 系统

    稳定性: 4 - API 冻结 提供一些基本的操作系统相关函数. 使用 require('os') 访问这个模块. os.tmpdir() 返回操作系统的默认临时文件夹 os.endianness() ...