网络编程基础

网络编程

概念 服务器概念:,是一个安装了服务器软件的计算机.
网络通信协议:两台计算机在做数据交互时要遵守的规则,协议会对数据的格式,速率等进行规定,只有都遵守了这个协议,才能完成数据交互.
通信三要素
1.[协议]
TCP:面向连接协议:
客户端和服务端想要完成数据交互,需要三次握手
第一次握手:客户端向服务端发送连接请求
第二次握手:服务器接收请求,响应,通知客户端,我接收到了请求
第三次握手:客户端再次向服务端发送确认信息,确认连接
缺点:效率低
优点:给数据提供了一个安全的传输环境
UDP:面向无连接协议:客户端和服务端交互时,无需确认连接,就可以传输数据
优点:效率高
缺点:数据不安全,有可能在传输的过程中丢失数据包
2.[IP地址]
a.概述:指互联网协议地址(Internet Protocol Address),俗称IP计算机的唯一标识
b.作用:可用于计算机和计算机之间的连接
[端口号]: 每一个应用程序的唯一标识
实现简单客户端和服务端的交互
Socket(服务器IP,服务器分配的端口号)
步骤:
1.创建Socket对象,指定服务器的IP,以及端口号
2.使用Socket对象调用getOutputStream,获取OutputStream对象,用于往服务器发请求
3.使用Socket对象调用getInputStream,获取InputStream对象,用于读取服务器响应回来的数据
4.关闭资源

//客户端
public class Client {
    public static void main(String[] args) throws IOException {
        //1.创建Socket对象,指定服务器的IP,以及端口号
        Socket socket = new Socket("127.0.0.1", 8888);
        //2.使用Socket对象调用getOutputStream,获取OutputStream对象,用于往服务器发请求
        OutputStream os = socket.getOutputStream();
        os.write("我想下载电影".getBytes());
        //3.使用Socket对象调用getInputStream,获取InputStream对象,用于读取服务器响应回来的数据
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        System.out.println(new String(bytes,0,len));
        //4.关闭资源
        is.close();
        os.close();
        socket.close();
    }
}

编写服务端
ServerSocket(int port) ->指定端口号
Socket accept() -> 监视是哪个客户端连接的我 , 哪个客户端连接服务端,accept方法返回的Socket就是代表哪个客户端对象,如果没有客户端连接我,accept自带阻塞功能,就一直在accept这里卡住不动,直到有客户端连接,程序才会继续往下执行
步骤:
1.创建ServerSocket指定端口号,用于客户端的连接
2.调用accept方法监视是有没有客户端连接,是哪个客户端连接
3.调用getInputStream,读取客户端发来的请求
4.调用getOutputStream,给客户端发响应结果
5.关闭资源

  //服务端
public class Server {
    public static void main(String[] args) throws IOException {
        //1.创建ServerSocket指定端口号,用于客户端的连接
        ServerSocket ss = new ServerSocket(8888);
        //2.调用accept方法监视是有没有客户端连接,是哪个客户端连接
        Socket socket = ss.accept();
        //3.调用getInputStream,读取客户端发来的请求
        InputStream is = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
        System.out.println(new String(bytes,0,len));
        //4.调用getOutputStream,给客户端发响应结果
        OutputStream os = socket.getOutputStream();
        os.write("给你一个电影".getBytes());
        //5.关闭资源 
        os.close();
        is.close();
        socket.close();
        ss.close();
    }
}

经验值传授:
Exception in thread “main” java.net.BindException: Address already in use: JVM_Bind
端口号冲突

文件上传

文件上传客户端以及服务端实现

//客户端
public class Client {
    public static void main(String[] args)throws IOException {
        //1.创建Socket对象,指定要连接服务端的端口号和ip
        Socket socket = new Socket("127.0.0.1", 8888);
        //2.创建FileInputStream用于读取本地上的图片
        FileInputStream fis = new FileInputStream("F:\\Idea\\io\\24.jpg");
      //3.调用Socket对象中的getOutputStream,用来将读取过来的图片写到服务器端
        OutputStream os = socket.getOutputStream();
        //4.边读边写
        byte[] bytes = new byte[1024];
        int len;
        while((len = fis.read(bytes))!=-1){
            os.write(bytes,0,len);
        }
        socket.shutdownOutput();
        System.out.println("==========以下代码为读取响应===========");
        //5.调用Socket对象中的getInputStream,用来读取服务端发来的响应结果
        InputStream is = socket.getInputStream();
        byte[] bytes1 = new byte[1024];
        int len1 = is.read(bytes1);
        System.out.println(new String(bytes1,0,len1));
        //6.关闭资源
        is.close();
        os.close();
        fis.close();
        socket.close();
    }
}
//服务端
public class Server {
    public static void main(String[] args)throws IOException {
        //1.创建ServerSocket对象,指定端口号
        ServerSocket ss = new ServerSocket(8888);
        //2.调用accept方法,等待连接的客户端对象
        Socket socket = ss.accept();
        //3.调用Socket中的getInputStream,读取客户端发来的图片字节
        InputStream is = socket.getInputStream();
        //4.创建FileOutputStream用于将读取过来的图片写到本地上
        String name = System.currentTimeMillis()+""+new Random().nextInt()+".jpg";
        FileOutputStream fos = new FileOutputStream("D:\\教学班级\\直播班级\\北京修正黑马JavaEE就业372期\\day16_网络编程\\资料\\img\\"+name);
        //5.边读边写
        byte[] bytes = new byte[1024];
        int len;
        while((len = is.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }
        System.out.println("==========以下代码为往客户端发送响应===========");
        //6.调用Socket对象中的getOutputStream,往客户端发送响应结果
        OutputStream os = socket.getOutputStream();
        os.write("上传成功!".getBytes());
        //7.关闭资源
        os.close();
        fos.close();
        is.close();
        socket.close();
    }
}

文件上传服务端实现(多线程)

public class Server_Thread {
    public static void main(String[] args) throws IOException {
        //1.创建ServerSocket对象,指定端口号
        ServerSocket ss = new ServerSocket(8888);

        while (true) {
            //2.调用accept方法,等待连接的客户端对象
            Socket socket = ss.accept();
            new Thread(new Runnable() {
                @Override
                public void run() {

                    try {
                  //3.调用Socket中的getInputStream,读取客户端发来的图片字节
                        InputStream is = socket.getInputStream();
                 //4.创建FileOutputStream用于将读取过来的图片写到本地上
                        String name = System.currentTimeMillis() + "" + new Random().nextInt() + ".jpg";
                        FileOutputStream fos = new FileOutputStream("D:\\教学班级\\直播班级\\北京修正黑马JavaEE就业372期\\day16_网络编程\\资料\\img\\" + name);
                        //5.边读边写
                        byte[] bytes = new byte[1024];
                        int len;
                        while ((len = is.read(bytes)) != -1) {
                            fos.write(bytes, 0, len);
                        }
              System.out.println("==========以下代码为往客户端发送响应");
               //6.调用Socket对象中的getOutputStream,往客户端发送响应结果
                        OutputStream os = socket.getOutputStream();
                        os.write("上传成功!".getBytes());
                        //7.关闭资源
                        os.close();
                        fos.close();
                        is.close();
                        //socket.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

文件上传服务器端(连接池版本)

public class Server_Pool {
    public static void main(String[] args)throws IOException {
        //创建线程池对象
        ExecutorService es = Executors.newFixedThreadPool(10);
        //1.创建ServerSocket对象,指定端口号
        ServerSocket ss = new ServerSocket(8888);
        while(true){
            //2.调用accept方法,等待连接的客户端对象
            Socket socket = ss.accept();
            es.submit(new Runnable() {
                @Override
                public void run() {
                    try{
                        //3.调用Socket中的getInputStream,读取客户端发来的图片字节
                        InputStream is = socket.getInputStream();
                        //4.创建FileOutputStream用于将读取过来的图片写到本地上
                        String name = System.currentTimeMillis()+""+new Random().nextInt()+".jpg";
                        FileOutputStream fos = new FileOutputStream("D:\\教学班级\\直播班级\\北京修正黑马JavaEE就业372期\\day16_网络编程\\资料\\img\\"+name);
                        //5.边读边写
                        byte[] bytes = new byte[1024];
                        int len;
                        while((len = is.read(bytes))!=-1){
                            fos.write(bytes,0,len);
                        }

                        System.out.println("==========以下代码为往客户端发送响应===========");
                        //6.调用Socket对象中的getOutputStream,往客户端发送响应结果
                        OutputStream os = socket.getOutputStream();
                        os.write("上传成功!".getBytes());

                        //7.关闭资源
                        os.close();
                        fos.close();
                        is.close();
                        //socket.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

BS架构服务器案例

/* BufferedReader(Reader in)
               BufferedReader的参数位置是Reader
               new BufferedReader的时候传递的只要是Reader的子类就ok
               如果我们想将InputStream转成BufferedReader
               我们就应该找一个跟InputStream有关的Reader的子类
               那么哪个Reader的子类和InputStream有关呢?
               InputStreamReader正好是Reader的子类,也正好和InputStream有关
               所以可以传递InputStreamReader作为BufferedReader的参数*/
public class BS {
    public static void main(String[] args)throws Exception {
        //1.创建ServerSocket对象
        ServerSocket ss = new ServerSocket(8888);
        while(true){
            //2.调用accept方法监视客户端对象
            Socket socket = ss.accept();
            //3.调用getInputStream读取客户端发来的请求
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String path = br.readLine();//GET /day16/web/index.html HTTP/1.1
            //3.1 调用split,根据空格切割,将path变成String数组
            String[] s = path.split(" ");
            String s1 = s[1];//     /day16/web/index.html
            //3.2 调用subString(1)从字符串的索引1开始分割,截取到最后
            String ioPath = s1.substring(1);
        //4.创建FileInputStream,根据解析出来的ioPath去本地上读取对应的网页
            FileInputStream fis = new FileInputStream(ioPath);
            //5.调用getOutputStream,将从本地上读取到的网页响应给浏览器(写)
            OutputStream os = socket.getOutputStream();
            //先把响应信息写到浏览器
            os.write("HTTP/1.1 200 OK\r\n".getBytes());
            os.write("Content-Type:text/html\r\n".getBytes());
            os.write("\r\n".getBytes());
            //6.边读编写
            byte[] bytes = new byte[1024];
            int len;
            while((len = fis.read(bytes))!=-1){
                os.write(bytes,0,len);
            }
            //7.关闭资源
            os.close();
            fis.close();
            br.close();
            is.close();
            socket.close();
        }
    }
}
/* BufferedReader(Reader in)
               BufferedReader的参数位置是Reader
               new BufferedReader的时候传递的只要是Reader的子类就ok
               如果我们想将InputStream转成BufferedReader
               我们就应该找一个跟InputStream有关的Reader的子类
              那么哪个Reader的子类和InputStream有关呢?
              InputStreamReader正好是Reader的子类,也正好和InputStream有关
              所以可以传递InputStreamReader作为BufferedReader的参数 */
public class BS_Thread {
    public static void main(String[] args)throws Exception {
        //1.创建ServerSocket对象
        ServerSocket ss = new ServerSocket(8888);
        while(true){
            //2.调用accept方法监视客户端对象
            Socket socket = ss.accept();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try{
                        //3.调用getInputStream读取客户端发来的请求
                        InputStream is = socket.getInputStream();
                        BufferedReader br = new BufferedReader(new InputStreamReader(is));
                        String path = br.readLine();//GET /day16/web/index.html HTTP/1.1
                        //3.1 调用split,根据空格切割,将path变成String数组
                        String[] s = path.split(" ");
                        String s1 = s[1];//     /day16/web/index.html
                        //3.2 调用subString(1)从字符串的索引1开始分割,截取到最后
                        String ioPath = s1.substring(1);
                        //4.创建FileInputStream,根据解析出来的ioPath去本地上读取对应的网页
                        FileInputStream fis = new FileInputStream(ioPath);
                        //5.调用getOutputStream,将从本地上读取到的网页响应给浏览器(写)
                        OutputStream os = socket.getOutputStream();
                        //先把响应信息写到浏览器
                        os.write("HTTP/1.1 200 OK\r\n".getBytes());
                        os.write("Content-Type:text/html\r\n".getBytes());
                        os.write("\r\n".getBytes());
                        //6.边读编写
                        byte[] bytes = new byte[1024];
                        int len;
                        while((len = fis.read(bytes))!=-1){
                            os.write(bytes,0,len);
                        }
                        //7.关闭资源
                        os.close();
                        fis.close();
                        br.close();
                        is.close();
                        socket.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值