网络通信学习笔记(三)---TCP通信及文件上传

简介: 网络通信学习笔记(三)---TCP通信及文件上传

1. TCP协议


1.1. TCP通信

因为我们上面说过,TCP是明确区分客户端与服务端的,所以我们编写代码的过程中必须要编写两个类分别代表客户端与服务端.

我们先编写客户端的代码:


public static void main(String[] args) throws IOException {
        Socket socket=null;
        OutputStream os=null;
        try {
            //首先先创建一个InetAddress对象,表明我们客户端过会是要和哪台服务器进行连接
            InetAddress serverIP=InetAddress.getByName("127.0.0.1");
            int port=9999;
            //之后我们创建一个连接连接到该服务器上
            socket=new Socket(serverIP,port);
            //因为我们是客户端所以我们需要给服务器发消息,所以我们再创建一个文件流,帮助我们写入数据
            os=socket.getOutputStream();
            //之后就是通过文件流来写入数据
            os.write("hi,you are here too".getBytes());
        }
        catch (IOException e){
            e.printStackTrace();
        }
    //这里最好就是关闭好连接,否则可能会出现下面的错误
    finally {
            os.close();
            socket.close();
        }
    }

服务端代码:

public static void main(String[] args) throws IOException {
        ServerSocket serverSocket=null;
        Socket socket=null;
        InputStream is=null;
        ByteArrayOutputStream baos=null;
        try {
            //创建客户端需要连接的服务端
            serverSocket=new ServerSocket(9999);
            while (true){
                //等待客户端连接过来
                socket=serverSocket.accept();
                //读取客户端的消息
                is=socket.getInputStream();
                baos=new ByteArrayOutputStream();
                byte[] buffer=new byte[1024];
                int len;
//            do {
//                len=is.read(buffer);
//                baos.write(buffer,0,len);
//            } while (is.available() != 0);
                while ((len=is.read(buffer))!=-1){
                    baos.write(buffer,0,len);
                }
                System.out.println(baos.toString());
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
        //这里最好就是关闭好连接,否则可能会出现下面的错误
        finally {
            baos.close();
            is.close();
            socket.close();
            serverSocket.close();
        }
    }

20200917113406219.png


所以最好还是将整个连接关闭好,否则可能会出现上述错误;

这种错误主要就是下面这个原因:

客户端发送完数据之后,并没有关闭socket连接,那么服务端在读取缓冲区的数据是就有可能会出现这样的错误,主要就是 读写操作出现冲突

效果如下:

image.gif


1.2. TCP文件上传


其实本质上这里和我们上面写的TCP通信其实是差不多的,只不过这里因为我们需要上传的是文件所以我们必须使用文件专属的流,所以需要使用 FileInputStream 与 FileOutputStream ,还有一个就是 关闭连接方面 ,这个关闭连接和上面的关闭连接不太一样,具体我们在下面的代码中具体讲.


其他的操作本质上就是一致的.


客户端:

 public static void main(String[] args) throws IOException {
        //创建一个Socket连接
        Socket socket=new Socket(InetAddress.getByName("127.0.0.1"),9000);
    //读取一个输出流
        OutputStream os=socket.getOutputStream();
    //读取文件
        FileInputStream fis=new FileInputStream(new File("新垣结衣.jpg"));
    //写出文件
        byte[] buffer = new byte[1024];
        int len;
        while ((len=fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        //确定服务器接收完毕后,才能断开连接
        InputStream inputStream1= socket.getInputStream();
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        byte[] buffer2=new byte[2048];
        int len2;
        while ((len2=inputStream1.read(buffer2))!=-1){
            baos.write(buffer2,0,len2);
        }
        System.out.println(baos.toString());
        //关闭连接
        baos.close();
        inputStream1.close();
        fis.close();;
        os.close();
        socket.close();
    }

服务端:

    public static void main(String[] args) throws IOException {
    //我有一个地址
        ServerSocket serverSocket=new ServerSocket(9000);
    //监听客户端的链接
        Socket socket=serverSocket.accept();//阻塞式监听,会一直等待客户端连接
    //获取输入流
        InputStream is=socket.getInputStream();
    //获取输出流
        FileOutputStream fos=new FileOutputStream(new File("receive.jpg"));
        byte[]buffer= new byte [1024];
        int len;
        while ((len=is.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }
    //通知客户端我接收完毕了
        OutputStream os=socket.getOutputStream();
        os.write("我接受好了,拜拜了您嘞".getBytes());
    //关闭连接
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }

如果我们只是这样这样写完的话,我们会发现一个奇怪的现象如下:

20200917113753167.gif

之前我们的客户端都是发完消息之后就直接关闭了,并且服务端也是接收到消息之后也不做其他的处理,所以整个的通信是能够正常结束的.


但是现在因为我们需要服务器在接收完数据之后告诉客户端我已经成功接收到数据了,你可以关闭连接了.所以客户端这边也是在等待接收服务端数据的状态所以这样就形成了思死锁的状态.就如下图所示:


2020091711383690.png

所以我们在客户端发送完数据之后需要断开socket的输出连接,否则服务端还是无法接收到客户端的信息的.


在客户端发送数据的代码后面添加这一段代码:


//      通知服务器,我已经结束了
        socket.shutdownOutput();//我已经传输完了


这样之后我们的文件上传就实现了,效果如下:


20200917113807130.gif


相关文章
|
Ubuntu 网络协议 Unix
02理解网络IO:实现服务与客户端通信
网络IO指客户端与服务端通过网络进行数据收发的过程,常见于微信、QQ等应用。本文详解如何用C语言实现一个支持多客户端连接的TCP服务端,涉及socket编程、线程处理及通信流程,并分析“一消息一线程”模式的优缺点。
217 0
|
7月前
|
网络协议 物联网
VB6网络通信软件上位机开发,TCP网络通信,读写数据并处理,完整源码下载
本文介绍使用VB6开发网络通信上位机客户端程序,涵盖Winsock控件的引入与使用,包括连接服务端、发送数据(如通过`Winsock1.SendData`方法)及接收数据(利用`Winsock1_DataArrival`事件)。代码实现TCP网络通信,可读写并处理16进制数据,适用于自动化和工业控制领域。提供完整源码下载,适合学习VB6网络程序开发。 下载链接:[完整源码](http://xzios.cn:86/WJGL/DownLoadDetial?Id=20)
275 12
|
8月前
|
canal 编解码 运维
飞天洛神云网络再度入选通信顶会 SIGCOMM'24
飞天洛神云网络再度入选通信顶会 SIGCOMM'24
292 12
|
8月前
|
人工智能 自然语言处理 决策智能
智能体竟能自行组建通信网络,还能自创协议提升通信效率
《一种适用于大型语言模型网络的可扩展通信协议》提出创新协议Agora,解决多智能体系统中的“通信三难困境”,即异构性、通用性和成本问题。Agora通过标准协议、结构化数据和自然语言三种通信格式,实现高效协作,支持复杂任务自动化。演示场景显示其在预订服务和天气预报等应用中的优越性能。论文地址:https://arxiv.org/pdf/2410.11905。
272 6
|
10月前
|
负载均衡 网络协议 算法
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
这网络层就像搭积木一样,上层协议都是基于下层协议搭出来的。不管是ping(用了ICMP协议)还是tcp本质上都是基于网络层IP协议的数据包,而到了物理层,都是二进制01串,都走网卡发出去了。 如果网络环境没发生变化,目的地又一样,那按道理说他们走的网络路径应该是一样的,什么情况下会不同呢? 我们就从路由这个话题聊起吧。
238 4
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
|
8月前
|
缓存 网络协议 安全
即时通讯初学者必知必会的20个网络编程和通信安全知识点
即时通讯IM应用开发的初学者很容易迷失在网络编程的复杂性以及通信安全的各种概念里,本文不涉及深度理论知识,尽量通过一句话或几句话让你快速了解20个相关的网络编程和通信安全知识点,希望能助你愉快地开始即时通讯应用开发。
172 0
|
8月前
|
网络协议 测试技术 Linux
Golang 实现轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库
gev 是一个基于 epoll 和 kqueue 实现的高性能事件循环库,适用于 Linux 和 macOS(Windows 暂不支持)。它支持多核多线程、动态扩容的 Ring Buffer 读写缓冲区、异步读写和 SO_REUSEPORT 端口重用。gev 使用少量 goroutine,监听连接并处理读写事件。性能测试显示其在不同配置下表现优异。安装命令:`go get -u github.com/Allenxuxu/gev`。
163 0
|
10月前
|
网络协议
TCP报文格式全解析:网络小白变高手的必读指南
本文深入解析TCP报文格式,涵盖源端口、目的端口、序号、确认序号、首部长度、标志字段、窗口大小、检验和、紧急指针及选项字段。每个字段的作用和意义详尽说明,帮助理解TCP协议如何确保可靠的数据传输,是互联网通信的基石。通过学习这些内容,读者可以更好地掌握TCP的工作原理及其在网络中的应用。
|
11月前
|
安全 搜索推荐 网络安全
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
294 11
|
11月前
|
网络协议
计算机网络与通信
计算机网络基本概念:了解计算机网络的定义、功能、分类和拓扑结构(如总线型、星型、环型、树形、网状等)。 网络通信原理:了解网络通信的基本原理、协议和技术,如TCP/IP协议、网络通信设备等。
197 3

热门文章

最新文章