TCP、UDP协议,java网络通信基础

本文详细解析了OSI参考模型及TCP/IP协议栈的工作原理,包括各层的功能及TCP与UDP的区别。并通过实例介绍了Socket编程的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • OSI模型与TCP/IP协议栈
  • 端口
  • TCP  UDP
  • Socket ServerScoket DatagramSocket

OSI参考模型

OSI(Open System Interconnect),即开放式系统互联。 一般都叫OSI参考模型,体系结构标准定义了网络互连的七层框架(物理层数据链路层网络层传输层会话层表示层应用层),针对攻城狮们,我们不需要过多的去关注物理层、数据链路层,

网络层:IP地址的寻址,查询互联网中某台服务器

传输层:(TCP/UDP)实现端到端的通信

会话层: 实现端到端的之间的交互信息

表示层: 端到端的之间的交互形式

应用层: :HTTPHTTPSFTPTELNET,SSH,SMTPPOP3等。



  • TCP/IP协议栈

 wKioL1SIBJKy7q8oAAEMHfbl-0E582.jpg

wKiom1SIBAHw1MybAAE_fDStMQg817.jpg

由于OSI模型和协议比较复杂,所以并没有得到广泛的应用。

端口

端口有什么用呢?我们知道,一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区 分不同的服务的。

TCP/UDP

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠、基于字节流的输层通信协议,TCP为了保证报文传输的可靠[1]  就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。

TCP三次握手的过程如下:
  1. 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
  2. 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入 SYN_RECV状态。
  3. 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。

UDP提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序



对比UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同,TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。与TCP不同,UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。TCP在现实当中就像我们打电话先拨通在说话,UDP就像是发短信

wKiom1SIBzHSMZ78AAF3CFFhIxI894.jpg

  • Socket ServerScoket DatagramSocket

TCP 套接字处理流程

UDP 套接字处理流程




--------参考资料------------

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class ClientTcp
{
    private static final String host = "localhost";
    
    private static final int port = 1999;
    
    public static void main(String[] args)
        throws IOException
    {
        Socket scoketClient = null;
        OutputStream writer = null;
        BufferedReader buffer = null;
        String readLine = null;
        try
        {
            while (true)
            {
                scoketClient = new Socket(host, port);
                writer = scoketClient.getOutputStream();
                buffer = new BufferedReader(new InputStreamReader(scoketClient.getInputStream()));
                
                int c;
                while ((c = System.in.read()) != -1)
                {
                    writer.write(c);
                    if (c == '\n')
                    {
                        writer.flush();
                        break;
                    }
                }
                System.out.println("Server:" + buffer.readLine());
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            scoketClient.close();
            writer.close();
            buffer.close();
        }
    }
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server
{
    
    static final int port = 1999;
    
    static final ExecutorService service = Executors.newFixedThreadPool(10);
    
    public static void main(String[] args)
        throws IOException
    {
        
        ServerSocket serverScoket = null;
        try
        {
            serverScoket = new ServerSocket(port);
            
            while (true)
            {
                Socket socket = serverScoket.accept();
                System.out.println(socket);
                service.submit(new Work(socket));
            }
        }
        catch (Exception e)
        {
            
            e.printStackTrace();
            
        }
        finally
        {
            serverScoket.close();
        }
    }
}

class Work implements Runnable
{
    
    Socket scoket;
    
    BufferedReader reader = null;
    
    BufferedWriter writer = null;
    
    public Work(Socket scoket)
        throws IOException
    {
        
        this.scoket = scoket;
        this.reader = new BufferedReader(new InputStreamReader(scoket.getInputStream()));
        this.writer = new BufferedWriter(new OutputStreamWriter(scoket.getOutputStream(), "UTF-8"));
        
    }
    
    @Override
    public void run()
    {
        
        String readLine = null;
        try
        {
            while ((readLine = reader.readLine()) != null)
            {
                System.out.println(readLine);
                int c;
                while ((c = System.in.read()) != -1)
                {
                    writer.write(c);
                    if (c == '\n')
                    {
                        writer.flush();
                        break;
                    }
                }
                break;
            }   
        }
        catch (IOException e)
        {
            
            e.printStackTrace();
            
        }
        finally
        {
            try
            {
                scoket.close();
                reader.close();
                writer.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class ClientUDP
{
    
    public static void main(String[] args)
        throws IOException
    {
        DatagramSocket client = null;
        try
        {
            client = new DatagramSocket();
            byte[] sendBytes = {'a', 'b', 'c'};
            byte[] recvBytes = new byte[1024];
            
            InetAddress ipAddress = InetAddress.getByName("localhost");
            DatagramPacket sendPackage = new DatagramPacket(sendBytes, sendBytes.length, ipAddress, 1999);
            client.send(sendPackage);
            
            DatagramPacket recvPackage = new DatagramPacket(recvBytes, recvBytes.length);
            client.receive(recvPackage);
            
            System.out.println(new String(recvPackage.getData(), "GBK"));
            
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            client.close();
        }
    }
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ServerUDP
{
    
    public static void main(String[] args)
        throws IOException
    {
        DatagramSocket client = null;
        byte[] sendBytes = {'h', 'e', 'l'};
        byte[] recvBytes = new byte[1024];
        try
        {
            client = new DatagramSocket(1999);
            while (true)
            {
                System.out.println("服务监听。。。。。");
                DatagramPacket revc = new DatagramPacket(recvBytes, recvBytes.length);
                client.receive(revc);
                System.out.println("Recv:" + new String(revc.getData()));
                
                DatagramPacket send =
                    new DatagramPacket(sendBytes, sendBytes.length, revc.getAddress(), revc.getPort());
                client.send(send);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            client.close();
        }
        
    }
    
}

《Java网路编程》

《百度百科》


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值