美文网首页程序员
Java网络编程(1)

Java网络编程(1)

作者: xianxun | 来源:发表于2019-08-21 19:44 被阅读0次

1.基本网络概念

网络

--网络是相互发送和接受数据的计算机和其他设备的集合;
--每一个设备就是一个网络节点(node);
--每一个计算机是一个主机(host)
--每个网络节点有地址;
--以太网分配物理地址;
--Internet服务器分配Internet地址;
--地址可以有标识名字,但是不与地址锁定;

IP、TCP和UDP

IP地址网络中计算机的唯一标识
--P地址是用一个点来分成四段的,在计算机内部IP地址是用四个字节来表示的,一个字节代表一段,每一个字节代表的数最大只能到达255。
--IPv4地址,4字节地址,例如192.168.6.190
--包的首部保护目的地址和源地址
--IPv4地址已经用完,目前在向IPv6地址过渡
--IPv6地址,16字节地址,例如FEDC:7654:3210:FEDC:BA98:7654:3210
域名(DNS)
--用于记忆主机名,并在使用时转换为ip地址
--IP地址会随着时间变换
--127.0.0.1表示本地回送地址
--IPv6的本地回送地址为::1
端口正在运行的程序的标识。
--每台计算机有65535个端口
--1到1023保留给已知服务

端口.png
客户/服务器模型
--服务端发送数据,客户端接收数据
--对等端通过服务器程序实现相互通信
TCP
建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低
--面向连接
--安全可靠
--效率稍低
--通过三次握手确保连接的建立
--举例:下载,打电话,QQ聊天(你在线吗,在线,就回应下,就开始聊天了)
UDP
将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快
--面向无连接
--不可靠
--速度快
--将数据封包传输,数据包最大64k
--举例:聊天留言,在线视频,视频会议,发短信,邮局包裹

网络通信三要素

IP地址:网络中设备的标识,不易记忆,可用主机名
端口号:用于标识进程的逻辑地址,不同进程的标识
传输协议(通讯的规则):常见协议:TCP,UDP

URL

URI=URL+URN
URI:Uniform Resource Identifier ,统一资源标志符。
URL:Uniform Resource Locator,统一资源定位符。
URN:Uniform Resource Name,统一资源命名。

TCP编程

--TCP是可靠的连接,TCP就像打电话,需要先打通对方电话,等待对方有回应后才会跟对方继续说话,也就是一定要确认可以发信息以后才会把信息发出去。TCP上传任何东西都是可靠的,只要两台机器上建立起了连接,在本机上发送的数据就一定能传到对方的机器上。
实例1
服务器端

//模拟服务器端
class Service {
    public static void main(String[] args) throws IOException {
        //创建服务器端 表明自己端口号8989
        ServerSocket ss = new ServerSocket(8989);
        //一旦有客户端来链接 就获取客户端的socket
        Socket clientSocket = ss.accept();
        //向客户端发送数据
        //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
        //bw.write("登陆成功");
        PrintStream ps = new PrintStream(clientSocket.getOutputStream());
        ps.println("登陆成功");

        //输出完毕 关掉输出流
        clientSocket.shutdownOutput();

        //-----接收客户端发送的数据---//
        BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        String line = null;
        while ((line = br.readLine() )!= null){
            System.out.println(line);
        }

    }
}

客户端

//模拟客户端
class Client{
    public static void main(String[] args) throws IOException {
        //1.创建用于通信的Scoket
        // 指明和谁通信:ip地址 端口号
        Socket socket = new Socket("127.0.0.1",8989);
        //接收服务器的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //向服务器发送数据
        //socket.getOutputStream();
        //读取数据
        String line = null;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        //---客户端向服务器发送数据---//
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println("你好啊!");
        socket.shutdownOutput();
    }
}

执行结果:


$FERE4RRV4E4}{SURXG)7ZX.png

![(UOO0B%@KH7%I1W3{4]09`Q.png](https://img.haomeiwen.com/i18945157/f927ea0e7a64e06d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

在上面结果可以看出,服务器与客户端都进行了数据的交换
实例2

/**
 * 手动输入内容发送
 * 客户<--> 1.文本 2.图片 3.视频 4.音频 <-->服务器端
 */
/**----模拟客户端----*/
class MyClient {
    public static void main(String[] args) {
        //链接服务器端的socket
        Socket socket =null;
        try {
            socket = new Socket("127.0.0.1",8989);

            //接收服务端发送的数据
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //从键盘输入的数据 发送给服务器

            String line = null;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("链接出错");
        }finally {
            //关闭链接
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
/**----模拟服务器端----*/
class MyServer {
    public static void main(String[] args) {
        //创建ServerSocket
        try(ServerSocket ss = new ServerSocket(8989)){//在括号里面会自动释放
            //监听客户端链接
            Socket socket = ss.accept();

            //从终端接收数据
            BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
            //创建向客户端输出的输出流
            PrintStream ps = new PrintStream(socket.getOutputStream());
            String line = null;

            while ((line = keyin.readLine()) != null){
                //调用刚刚创建的客户端输出流 发送信息给客户端
                ps.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

上面程序执行的结果是:服务端可以从键盘输入数据,在发送给客户端
实例3

package day13media;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 客户端向服务器端上传图片
 */

public class MyClass {
}
/**----模拟客户端----*/
class Client{
    public static void main(String[] args) throws IOException {
        //链接服务器端 获取socket
        Socket socket = new Socket("127.0.0.1",8989);
        //创建服务器端对应的输入流 用于接收服务器端发送过来的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println(br.readLine());
        //向服务器端发送图片
        //1.将文件写入到内存
        String path ="C://Users//18168//Desktop//yz.jpg";
        FileInputStream fis = new FileInputStream(path);
        //创建一个输出流
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        byte[] buf = new byte[1024];
        int len = -1;
        while((len = fis.read(buf)) != -1){
            //开始向输出流中写入数据
            bos.write(buf,0,len);
        }
        socket.shutdownOutput();
    }
}
/**----模拟服务器端----*/
class Server{
    public static void main(String[] args) throws IOException {
        //创建服务器端的serverSocket
        ServerSocket ss = new ServerSocket(8989);
        //监听客户端的链接,一但有客户端来链接就能得到socket,如果没有客户端来链接,服务器就会一直等待
        Socket socket = ss.accept();
        //创建客户端对应的输出流 用于向客户端发送数据
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println("链接成功,可以发送数据!");

        //接收客户端传递过来的图片 就是接上面客户端的输出流
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        //文件对应的输出流  也就是将获取的数据保存
        String path ="C://Users//18168//AndroidStudioProjects//java3//Java3//src//main//java//day13media/yz1.jpg";
        //创建写入的对象 并且指定要写入的路径
        FileOutputStream fos = new FileOutputStream(path);
        byte[] buf = new byte[1024];
        int len = -1;
        while ((len = bis.read(buf)) != -1){
            //开始写数据
            fos.write(buf,0,len);
        }
    }
}

执行结果:在对应的目录下有一张名字为:yz1.ipg的图片
实例4
--创建群聊,用一台电脑当服务器,其他电脑通过服务器的ip链接服务器,就可以实现多人聊天,这个实例涉及到多线程

package group;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/**
 * 群聊天
 * 1.在服务器端维护一个数组【socket】
 * 客户端和服务器端都可以随意的发送内容
 * 2.客户端:
 *      主线程:接收终端输入 将终端输入的数据发送给服务器
 *      子线程:接收来自服务器端发送的数据
 * 3.服务器端:
 *      主线程:接收终端输入 将终端输入的数据发送给客户端
 *      子线程:接收来自客户端发送的数据
 */

/**----创建服务器端主线程----*/
class Server{
    //保存每一个链接过来的对象
    public static ArrayList<Socket> sockets = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(8989);

        //不停的等待客户端的链接
        while (true) {
            Socket socket = ss.accept();
            //当有客户端链接过来就保存
            sockets.add(socket);

            //开启一个线程处理每个客户端的输入
            new ServerThread(socket).start();
        }

    }
}
/**----创建服务器端子线程----*/
class ServerThread extends Thread {
    private Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String lint = null;
            while ((lint = br.readLine()) != null) {
                //群发消息
                //遍历Server维护的数组
                for (Socket s:Server.sockets) {
                    //向socket对应的客户发送消息
                    PrintStream ps = new PrintStream(s.getOutputStream());
                    ps.println(lint);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    //为了不浪费资源,要将流关闭
                    br.close();
                }
                if (socket != null) {
                    //为了不浪费资源,要将流关闭
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

/**----模拟客户端----*/
class Client{
    public static void main(String[] args) throws IOException {
        //这里指明服务器的ip地址和端口号
        Socket socket = new Socket("10.129.28.253",6666);

        //用一个子线程处理服务器端的数据
        new Thread(new ClientThread(socket)).start();

        //主线程处理终端输入并且给服务器发送
        BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
        PrintStream ps = new PrintStream(socket.getOutputStream());
        String line = null;
        while ((line = keyin.readLine()) != null){
            ps.println(line);
        }

    }
}
/**----创建客户端子线程----*/
class ClientThread implements Runnable{
    private Socket socket;

    public ClientThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        //为了使finally能使用到这个,将其的作用域扩大
        BufferedReader br = null;
        try {
            //获取服务器输入流对象
            br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = null;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (br != null){
                    //为了不浪费资源,要将流关闭
                    br.close();
                }
                if (socket != null){
                    //为了不浪费资源,要将流关闭
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

这个例子还有很多需要完善的地方,后期再慢慢更新!

感悟

学到这里慢慢的感觉java的乐趣来了,不再是那些枯燥的类与继承,而是一些比较好玩的编程,虽然看似简单,可是后面这些再也不是单一的知识点,而是要将前面学习的很多东西联系起来!

相关文章

  • 《Netty实战》读书笔记01——第一章

    第 1 章 笔记 Java 网络编程 早期Java的网络编程,需要学习很多C语言套接字(Socket)的知识,但...

  • day26

    1:网络编程(理解)## (1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享 (2)网络编程模型 ...

  • IO

    java网络编程 阻塞IO NIO 1. java网络编程 基础知识1.ip地址和端口号2.tcp/udp协议3....

  • Java网络编程(第四版) PDF 超清版

    《Java网络编程(第四版)》是一本关于Java编程相关的电子书资源,介绍了关于Java、网络编程、Java编程方...

  • 1 Java网络编程

    java网络编程 1 基础知识1)ip地址和端口号ip地址,一个通讯实体端口号,用于区分不同的通讯程序2)tcp/...

  • Java网络编程(1)

    1.基本网络概念 网络 --网络是相互发送和接受数据的计算机和其他设备的集合;--每一个设备就是一个网络节点(no...

  • Android应用开发:网络编程2

    网络编程 Java基础:网络编程 Uri、URL、UriMatcher、ContentUris详解 Android...

  • Http协议

    网络编程 Java基础:网络编程 Uri、URL、UriMatcher、ContentUris详解 Android...

  • 2018-2019 目标技术栈

    一、java基础 1.Java 集合 2.Java 线程 3.Java io变成 4.Java 网络编程 二、my...

  • Netty

    一、网络编程基础原理 1 网络编程(Socket)概念 首先注意,Socket不是Java中独有的概念,而是一个语...

网友评论

    本文标题:Java网络编程(1)

    本文链接:https://www.haomeiwen.com/subject/vygisctx.html