网络编程

1.网络编程的目的:无线电台,信息交换

怎么做:
定位IP地址
.传输数据

2.网络通信的要素

如何实现网络通信

IP

端口号

协议:

TCP/IP参考模型
转至CSDN
在这里插入图片描述

TCP/IP:建立数据管道,无限制,面向连接,效率低,可靠。(打电话)

UDP:数据打包,有限制,不连接,效率高,不可靠。(发短信、视频会议)

小结:

  1. 网络编程中有两个主要的问题:如何准确的定位到网络上的一台和多台主机 ping网址/IP

找到主机之后如何进行通信

  1. 网络编程中的要素
    IP和端口号 IP类
    网络通信写协议 UDP和TCP类
  2. 万物皆对象

3.IP

IP地址: InetAddress

3.1 127.0.0.1:本机localhost

127.0.0.1 /  本机localhost
ping ipaddress  #检查网络是否畅通

3.2 ip地址分类

ipv4/ipv6:
本机地址:127.0.0.1
IPV4:4个字节, 0-255 , 30亿都在北美
IPV6:16个字节 8个无符号整数

3.3公网 和 私网
ABCD类地址
192.168.xx.xx给内部组织使用

cn域名是中国,com是国际

4.查询本机地址和网站地址的方法

InetAddress的构造函数不是公开的(public),所以需要通过它提供的静态方法来获取,有以下的方法:

getByname() 方法
参数:
host - 指定的主机,或 null。
返回:
给定主机名的 IP 地址。

 try {
         InetAddress i=InetAddress.getByName("www.baidu.com");
            System.out.println(i);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        //查询本机地址三种
        try {
            InetAddress i1=InetAddress.getByName("127.0.0.1");

            InetAddress i2=InetAddress.getByName("localhost");

            InetAddress i3=InetAddress.getLocalHost();


        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

4.端口 (PID)
端口表示计算机上的一个程序的进程

不同的进程有不同的端口号!用来区分软件
端口是由2个字节组成的,被规定能跑0-65535个

我们使用地址+端口号,就可以保证数据准确无误的发到计算机指定软件上

端口分类:

HTTP:80 www.baidu.com:80
HTTPS:443
FTP:21
Telent:23
程序注册端口:1024-49151

MySQL:3306
Oracle:1521
Tomcat:8080

netstat -ano 查看所有端口

netstat -ano 查看所有端口
netstat -ano|findstr"PID"  查看指定端口
tastlist|findstr  "PID" 查看指定端口的进程

5.通信协议

**网络通信协议:**速率,传输码率,代码结构,传输控制

TCP/IP协议是一组协议

TCP:用户传输协议
UDP:用户数据报协议

TCP:打电话

  1. 连接,稳定
  2. 三次握手,四次挥手
    三次握手:

A:我要开始连接了 (提问)
B: 我知道了,开始吧 (回复)
A:开始连接,连接ing (回复)

四次挥手
A:我准备走了 (提问)
B:你要走了吗 (思考)
B: 你走了吗 (回复)
A: 我走了 (回复)

3.客户端和服务端 CS

UDP:发短信

  1. 不连接,不稳定
  2. 客户端,服务端,无明确界限
  3. 不管能不能准备好都能发给你。
  4. DDOS 洪水攻击

5.TCP 通信程序

  • 启动服务器

  • 客户端启动,并请求客户端

  • 他们要连接,而连接需要一个IO对象(字节流对象
    在这里插入图片描述
    下面是具体的实现步骤
    我们要读取本地的一个文件,然后上传到服务器,并将其保存到本地。
    服务器:
    注意:

  • 从第一步开始就要放在while循环里面,保证服务器是一直打开的。

  • 接下来我们写一个线程,每次调用一个客户端就启动一个线程,剩下的2 3 4 …7步骤就放到run方法里面

while(true)
{
1. Socket socket = serverSocket.accept();

//多线程
new thread(new Runable())
{
@override
	public void run ()
	{
		try
		{
		2.3...7}
	
	}

}.start();


}

1 . 直接创建seversocket类对象,用它的accept方法获取客户端的socket对象

   Socket socket = serverSocket.accept();

准备工作2.3

2 . 判断一下文件是否存在 File file = new File("E:\\load"); if (!file.exists()) { file.mkdirs(); }

// 优化:文件名不能一直是一个,应该随机命名 毫秒+随机数+.jpg
                        
 String filename ="文件"+System.currentTimeMillis()+new Random().nextInt(999999)+".jpg";
                       

filename是文件名

3 . 创建本地字节输出流上传到硬盘,构造方法中绑定输出的目的地
fileOutputStream = new FileOutputStream(file + “\”+filename); 传输文件+随机文件名

4.5上传本地

4 .创建网络字节输入流,inputstream im =socket对象.getinputstream()读取文件

5 . 创建一个字节数组加快上传的速度 用网络字节输入流对象.read 网络读取,本地上传


                       byte[] bytes = new byte[1024];
                       int len = 0;
                       while ((len = inputStream.read(bytes)) != -1) {
                           fileOutputStream.write(bytes, 0, len);
                       }

6 . 网络字节输出流中write方法 反馈信息给客户端

   OutputStream outputStream = socket.getOutputStream();
 outputStream.write("上传成功".getBytes());

7.关闭资源,把要关闭的流都关闭了。

 fileOutputStream.close();
  socket.close();

客户端
1 . 本地字节输入流对象 读取上传的文件
2. 创建客户端对象,将文件通过网络字符输出流上传,绑定端口号

Socket socket=new Socket(“localhost”,8888);

3.获取网络字节输出流对象
OutputStream outputStream=socket.getOutputStream();

4.创建字节数组加速上传, 本地输入流读取 网络输出流上传

  byte [] bytes=new byte[1024];
    int len=0;
    while ((len=fileInputStream.read(bytes))!=-1)
    {
     //5.用网络字节输出流上传文件
        outputStream.write(bytes,0,len);
    }
    //** 优化:Socket对象禁用输出流
     socket.shutdownOutput();

6 .和服务器交互---------------------------------

7.获取网络字节输入流,读取服务器发回来的信息

 InputStream inputStream=socket.getInputStream();
    while ((len=inputStream.read(bytes))!=-1)
    {
        System.out.println(new String(bytes,0,len));
    }

8.关闭流,要用到的流都关掉。 流对象.close()

5.1客户机和服务器交互的步骤

在这里插入图片描述

下面是交互的代码:

客户机:

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

public class TCPClient {
    public static void main(String[] args) throws IOException {

        //1.创建客户端对象,给ip和端口
        Socket socket =new Socket("127.0.0.1",8888);
        //2.使用Socket对象中的getOutputStream方法获取网络字节输出流对象
        OutputStream os=socket.getOutputStream();

        //3.使用网络字节输出流对象中的write方法,给服务器发送数据
        os.write("你好服务器".getBytes());

        //4.用socket获取网络字节输入流   读取字节数组
        InputStream im=socket.getInputStream();

        //5.利用im字节输入流对象读取服务器返回的数据

        //这里自建一个数组来模拟
        byte [] bytes=new byte[1024];

        int len=im.read(bytes);
        System.out.println(new String(bytes, 0,len));

         //6.释放资源
         socket.close();

    }
}

服务器端

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

public class TCPServer {
    public static void main(String[] args) throws IOException {
        //1.创建服务器ServerSocket对象,和系统指定的端口号
        ServerSocket serverSocket=new ServerSocket(8888);

        //2.使用ServerSocket.accept 方法 获取客户端对象socket
        Socket socket=serverSocket.accept();

        //3.用socket获取网络字节输入流
        InputStream im=socket.getInputStream();

     // 4.利用im字节输入流对象读取数据    读取字节数组

        //这里自建一个数组来模拟

        byte [] bytes=new byte[1024];

        int len=im.read(bytes);
        System.out.println(new String(bytes,0,len));


        //5.用socket获取网络字节输出流
        OutputStream os=socket.getOutputStream();

        //6.利用字节输出流对象os,给客户端写数据
        os.write("收到谢谢".getBytes());

        //7.释放资源
        socket.close();
        serverSocket.close();
    }
}

5.2 文件上传案例

原理:客户端读取文件,把文件上传到服务器,服务器再把上传的文件保存在服务器的硬盘上

在这里插入图片描述

下面是代码实现

服务器

package com.testinternet;

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

public class TCPServer {
    public static void main(String[] args) throws IOException {

 //1 创建服务器对象 对应端口号
        ServerSocket serverSocket=new ServerSocket(8888);

  // 2 获取客户端的socket

        //** 优化:服务器不用关闭,是它一直处于激活的状态 while循环
        while (true) {
            Socket socket = serverSocket.accept();

            // ** 优化:有一个客户端上传文件,就开始一个线程,完成文件的上传。
           new Thread(new Runnable() {
               @Override
               public void run() {

                   FileOutputStream fileOutputStream = null;
                   try {
                       //3 创建网络字节输入流
                       InputStream inputStream = socket.getInputStream();


                       //4 判断一下目标文件夹是否存在
                       File file = new File("E:\\load");
                       if (!file.exists()) {
                           file.mkdirs();
                       }
                       /*
                        ** 优化:文件名不能一直是一个,应该随机命名 毫秒+随机数+.jpg
                        */
                       String filename ="文件"+System.currentTimeMillis()+new Random().nextInt(999999)+".jpg";

                       //5 创建本地字节输出流上传到硬盘,构造方法中绑定输出的目的地
                       fileOutputStream = new FileOutputStream(file + "\\"+filename);

                       //6.创建一个字节数组加快上传的速度 用网络字节输入流对象.read  网络读取,本地上传
                       byte[] bytes = new byte[1024];
                       int len = 0;
                       while ((len = inputStream.read(bytes)) != -1) {
                           fileOutputStream.write(bytes, 0, len);
                       }


                       //7 网络字节输出流中write方法 反馈信息给客户端
                       OutputStream outputStream = socket.getOutputStream();

                       outputStream.write("上传成功".getBytes());

                       //8 关闭资源
                       fileOutputStream.close();
                       socket.close();



                   } catch (IOException e) {
                       e.printStackTrace();
                   }


               }
           }).start();

        }

    }
}
/*
出现问题:
read方法读取不到结束标记,所以程序不会停止
所以我们在客户端可以使用socket对象.shutdown方法禁用网络输出流

*/

客户端

package com.testinternet;

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

public class TCPClient {
    public static void main(String[] args) throws IOException {

        //1 本地字节输入流对象 读取上传的文件
        FileInputStream fileInputStream=new FileInputStream("D:\\1.jpg");
        //2 创建客户端对象,将文件通过网络字符输出流上传,绑定端口号
        Socket socket=new Socket("localhost",8888);

         //3 获取网络字节输出流对象
   OutputStream outputStream=socket.getOutputStream();



   // 4.创建字节数组加速上传, 本地输入流读取 网络输出流上传
        byte [] bytes=new byte[1024];
        int len=0;
        while ((len=fileInputStream.read(bytes))!=-1)
        {
         //5.用网络字节输出流上传文件
            outputStream.write(bytes,0,len);
        }
        //** 优化:Socket对象禁用输出流
        socket.shutdownOutput();


        // 和服务器交互---------------------------------


        //6 获取网络字节输入流,读取服务器发回来的信息
       InputStream inputStream=socket.getInputStream();
        while ((len=inputStream.read(bytes))!=-1)
        {
            System.out.println(new String(bytes,0,len));
        }


   inputStream.close();
   outputStream.close();
   socket.close();



    }
}

总结:

1.客户端和服务器的交互是通过Socket类来交互
2.服务器是不能关闭的,它要在循环里面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值