socket 实现网络互动

在写 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();
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本章讨论TCP/IP体系中运输层最重要的两种协议:UDP和TCP。必须弄清TCP的各种机制(如面向连接的可靠服务、...
    dmmy大印阅读 998评论 0 0
  • 个人认为,Goodboy1881先生的TCP /IP 协议详解学习博客系列博客是一部非常精彩的学习笔记,这虽然只是...
    贰零壹柒_fc10阅读 5,100评论 0 8
  • 文/郭同学啊 01. 你不知道的是:“有那么一个卑微的女孩曾经那样深深地喜欢过你”。 吴桐,请原谅我这样直接称呼你...
    郭同学啊阅读 306评论 0 1
  • 【0529今日话题】 你看过的,最美丽的风景是什么?(欢迎图片,哈哈,但最好不要只是图片) 从我家后门拍的。五月早...
    梓毓爸阅读 154评论 0 1
  • 20岁 走在社会上 有时候会遇到一些心仪的人 可是不敢上前 没有身材 没有才华 我只不过是一个普通再普通不过的人 ...
    旧时光Fade阅读 175评论 0 1