美文网首页
socket 实现网络互动

socket 实现网络互动

作者: flyHunter雄 | 来源:发表于2017-04-24 13:09 被阅读0次

    在写 socket 之前先给大家介绍下 TCP 和 UDP
    TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。通俗说,它是事先为所发送的数据开辟出连接好的通道,然后再进行数据发送;而UDP则不为IP提供可靠性、流控或差错恢复功能。

    面向连接的TCP
    “面向连接”就是在正式通信前必须要与对方建立起连接。比如你给别人打电话,必须等线路接通了、对方拿起话筒才能相互通话。

    TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地发往网络上的其他计算机,对可靠性要求高的数据通信系统往往使用TCP协议传输数据。

    面向非连接的UDP协议
    “面向非连接”就是在正式通信前不必与对方先建立连接,不管对方状态就直接发送。与手机短信非常相似:你在发短信的时候,只需要输入对方手机号就OK了。

    UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去!

    TCP与UDP区别总结:

    1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
    2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
    3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
    UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
    4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
    5、TCP首部开销20字节;UDP的首部开销小,只有8个字节
    6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

    UDP如何实现可靠传输

    由于在传输层UDP已经是不可靠的连接,那就要在应用层自己实现一些保障可靠传输的机制

    简单来讲,要使用UDP来构建可靠的面向连接的数据传输,就要实现类似于TCP协议的

    超时重传(定时器)
    有序接受 (添加包序号)
    应答确认 (Seq/Ack应答机制)
    滑动窗口流量控制等机制 (滑动窗口协议)

    等于说要在传输层的上一层(或者直接在应用层)实现TCP协议的可靠数据传输机制,比如使用UDP数据包+序列号,UDP数据包+时间戳等方法。

    java 代码实现 tcp

    服务端server

    public class UploadServer {
    
      public static void main(String[] args) throws IOException {
        //1.创建一个ServerSocket
        ServerSocket serverSocket = new ServerSocket(8888);     
        
        //2.使用ServerSocket监听用户的请求
        Socket socket = serverSocket.accept();      
        
        //3.接收用户的请求数据并复制到本地
        //创建流(输入流和输出流)
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:/women2.mp3"));
        //使用流(输入流和输出流)
        byte [] buf = new byte[1024];
        int len = bis.read(buf);
        while(len !=-1){
            //写一个字节
            bos.write(buf, 0, len);
            //输出
            //System.out.println((char)n);
            //读一个字节
            len = bis.read(buf);
        }       
        //手动刷新(输出缓冲区内容写入文件)
        //bos.flush();
        //关闭流(输入流和输出流)
        //bis.close(); //关闭流同时关闭socket
        socket.shutdownInput();
        bos.close();
        
        //4.给客户端响应(上传成功)
        BufferedOutputStream bos2 = new BufferedOutputStream(socket.getOutputStream());
        bos2.write("上传成功".getBytes());
        bos2.flush();
        //5.关闭资源
        bis.close();
        bos2.close();
        socket.close();
        serverSocket.close();
    
      }
    }
    

    客户端client

    public class UploadClient {
    
    public static void main(String[] args) throws UnknownHostException, IOException {
        //1.创建一个Socket,连接服务器端
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);       
        
        //2.复制文件到服务器端
        //创建流(输入流和输出流)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("d:/women.mp3")));
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        //使用流(输入流和输出流)
        byte [] buf = new byte[1024];
        int len = bis.read(buf);
        while(len !=-1){
            //写一个字节
            bos.write(buf, 0, len);
            //输出
            //System.out.println((char)n);
            //读一个字节
            len = bis.read(buf);
        }       
        //关闭流(输入流和输出流)
        bis.close();
        //bos.close();
        socket.shutdownOutput(); //只想关闭输出流,但是不想同时关闭socket
        //3.接收响应信息并输出
        BufferedInputStream bis2 = new BufferedInputStream(socket.getInputStream());
        len = bis2.read(buf);
        System.out.println(len);
        System.out.println(new String(buf,0,len));
        //4.关闭资源
        bos.close();
        socket.close();
    }
    
    }
    

    java 代码实现 udp

    服务端 server 代码
    
    public class AskServer {
      public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.创建一个DatagramSocket,用来发送或者接收数据
        DatagramSocket socket = new DatagramSocket(8888);//8888  接收数据的端口        
        
        //2.使用DatagramSocket接收数据
        byte [] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);        
        socket.receive(packet); 
        //System.out.println("客户端发来的消息:"+new String(packet.getData(),0,packet.getLength()));
        ByteArrayInputStream bais = new ByteArrayInputStream(packet.getData(), 0, packet.getLength());
        ObjectInputStream ois = new ObjectInputStream(bais);
        //System.out.println(ois.readInt());
        //System.out.println(ois.readDouble());
        System.out.println(ois.readObject());
            
        //3.使用DatagramSocket发送数据
        String  reply = "你在线吗?";
        byte [] buf2 =reply.getBytes();
        DatagramPacket packet2 = new DatagramPacket(buf2, buf2.length, packet.getAddress(), packet.getPort());
        socket.send(packet2);
        
        //4.关闭资源
        ois.close();
        socket.close();     
      }
    }
    

    客户端client 代码

    public class AskClient {
    
      public static void main(String[] args) throws IOException {
        //1.创建一个DatagramSocket,用来发送或者接收数据
        DatagramSocket socket = new DatagramSocket(9999);//接收数据的端口
        
        //2.使用DatagramSocket发送数据
        //int num = 10;
        //double pi=3.14;
        User user = new User("liao","xiong");
        //各种数据类型------> byte [] 
        //// start!!!!
        ByteArrayOutputStream  baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        //oos.writeInt(num);
        //oos.writeDouble(pi);
        oos.writeObject(user);
        byte [] buf = baos.toByteArray();
        /////end!
        DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 8888);
        socket.send(packet);
        
        //3.使用DatagramSocket接收数据
        byte [] buf2 = new byte[1024];
        DatagramPacket packet2 = new DatagramPacket(buf2, buf2.length);     
        socket.receive(packet2);
        System.out.println("服务器端的反馈:"+new String(buf2,0,packet2.getLength()));
        
        //4.关闭资源
        oos.close();
        socket.close();
      }
    }

    相关文章

      网友评论

          本文标题:socket 实现网络互动

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