java网络编程基础-传输层协议TCP&UDP

x33g5p2x  于2021-11-22 转载在 Java  
字(5.3k)|赞(0)|评价(0)|浏览(320)

一.网络编程基础

1.网络和网卡
网络是当前信息技术的第一推动力
每个计算机设备上都有若干个网卡
每个网卡上都有全球唯一的单独的硬件地址,MAC地址

2.IP地址:每个网卡/机器都有一个或多个IP地址

IPV4:192.168.0.100,每段0到255
IPV6:128bit长,分为8段,每段4个16进制数
本机保留IP:127.0.0.1
Windows通过ipconfig查询,Linux/Mac通过ifconfig

3.Port端口,0-65535

0-1023,OS以及占用了,80是Web,23是telent
1024-65535,一般程序可使用(谨防冲突)
两台机器通讯是在IP+Port上进行的
Windows/Linux/Mac通过netstat -an查询

4.公网(万维网/互联网)和内网(局域网)

网络是分层的
最外层是公网/互联网
底下的每层都是内网
IP地址可以在每个层次的网使用
tracert可看当前机器和目标机器的访问中继

5.传输层通讯协议

TCP(Transmission Control Protocol)
传输控制协议,面向连接的协议
两台机器的可靠无差错的数据传输
双向字节流传递
UDP(User Datagram Protocol)
用户数据报协议,面向无连接的协议
不保证可靠的数据传输
速度快,也可以在较差网络环境下使用

6.计算机通讯

数据从一个IP的port出发(发送方),运输到另一个IP的port(接收方)

二.UDP:无连接无状态的通讯协议

1.特性
发送方发消息,如果接收方刚好在目的地,则可以接收,如果不在,那这个消息就丢失了
发送方也无法得知是否发送成功
UDP的好处就是简单,节省,经济

2.思路

通过DatagramSocket建立通讯的数据管道ds
通过DatagramPacket建立数据的集装箱dp
向DatagramPacket中传入消息字节码和消息字节码长度
若为发送方,则传入地址标签:目的地IP+Port
通过InetAddress.getByName(“IP”)传入地址
send方法实现发送和receive方法实现接收
接收方必须早于发起方执行

3.demo:UdpRecv

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

public class UdpRecv {
    public static void main(String[] args) throws Exception
    {
        //定义管道为本机3000端口
        DatagramSocket ds=new DatagramSocket(3000);
        //定义字节数组存放信息
        byte [] buf=new byte[1024];
        //定义集装箱,用来封装信息
        DatagramPacket dp = new DatagramPacket(buf,1024);

        System.out.println("UdpRecv: 我在等待信息");
        //等待信息,如果有信息过来,则会封装在dp中
        //如果没有信息过来,则会造成阻塞
        ds.receive(dp);
        System.out.println("UdpRecv: 我接收到信息");
        
        //dp.getAddress().getHostAddress()方法获取IP
        //dp.getPort()方法获取Port
        String strRecv=new String(dp.getData()) +
                " from " + dp.getAddress().getHostAddress()+":"+dp.getPort();
        //打印信息和信息的来源地址
        System.out.println(strRecv);

        //线程暂停1s
        Thread.sleep(1000);
        
        //设置将要发送的信息
        String str="hello yh";
        //定义集装箱,装入dp内容和长度并且贴了目的地
        //目的地为127.0.0.1:3000
        //str.getBytes()方法把str类型转化为byte类型
        //str.length()
        //地址标签:目的地IP+Port
        DatagramPacket dp2=new DatagramPacket(str.getBytes(),str.length(),
                InetAddress.getByName("127.0.0.1"),dp.getPort());
        
        System.out.println("UdpRecv: 我要发送信息");
        //发送信息
        ds.send(dp2);
        System.out.println("UdpRecv: 我发送信息结束");
        
        //关闭管道
        ds.close();
    }
}

4.demo:UdpSend

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;

public class UdpSend {
    public static void main(String [] args) throws Exception
    {
        //DatagramSocket:通讯的数据管道
        //定义管道
        DatagramSocket ds = new DatagramSocket();
        //定义将要发送的信息
        String str = "hello henrik";
        //定义集装箱,装入dp内容和长度并且贴了目的地
        //目的地为127.0.0.1:3000
        //str.getBytes()方法把str类型转化为byte类型
        //str.length()
        //地址标签:目的地IP+Port
        DatagramPacket dp = new DatagramPacket(str.getBytes(),str.length(),
                InetAddress.getByName("127.0.0.1"),3000);

        System.out.println("UdpSend: 我要发送信息");
        //发送信息
        ds.send(dp);
        System.out.println("UdpSend: 我发送信息结束");

        //进程暂停1s
        Thread.sleep(1000);

        //定义字节数组存放信息
        byte [] buf=new byte[1024];
        //定义集装箱用来封装信息
        DatagramPacket dp2 = new DatagramPacket(buf,1024);

        System.out.println("UdpSend: 我在等待信息");
        ds.receive(dp2);
        System.out.println("UdpSend: 我接收到信息");

        //dp.getAddress().getHostAddress()方法获取IP
        //dp.getPort()方法获取Port
        String str2 = new String(dp2.getData()) +
                " from " + dp2.getAddress().getHostAddress()+":"+dp2.getPort();
        //打印信息和信息的来源地址
        System.out.println(str2);

        //关闭管道
        ds.close();
    }
}

5.效果

三.TCP:有连接,保证可靠的通讯协议

1.思路
服务器创建一个ServerSocket,等待连接
客户机创建一个Socket,连接到服务器
服务器的ServerSocket接收到连接,创建一个Socket和客户的Socket建立专线连接,后续服务器和客户机的对话(这一对Socket)会在一个单独的线程(服务端)上运行
服务端的ServerSocket继续等待连接

2.特性

服务端等待响应时,处于阻塞状态
服务端可以同时响应多个客户端
服务端每接受一个客户端,就启动一个独立的线程与之对应
客户端和服务端都可以选择关闭这对Socket的通道
ServerSocket作为服务器的码头,需要绑定port,如果有多块网卡,需要绑定一个ip地址
Socket作为运输通道,客户端往Socket输入流写入数据,送到服务端,从Socket输出流取服务器端过来的数据,服务端反之亦然

3.demo:TcpServer

import java.net.*;
import java.io.*;
import java.nio.charset.StandardCharsets;

public class TcpServer
{
	public static void main(String [] args) 
	{
		try{
			//驻守在8001端口
			ServerSocket ss = new ServerSocket(8001);
			//等待客户端连接
			Socket s = ss.accept();
			//阻塞提示
			System.out.println("welcome to the java world");
			//有人连接上打开输入流
			InputStream ips = s.getInputStream();
			//打开输出流
			OutputStream ops = s.getOutputStream();
			//同一个通道,服务端的输出流输入流就是客户端的输出流输入流

			//输出一句话给客户端
			ops.write("hello client".getBytes());

			//从客户端读取一句话
			BufferedReader br = new BufferedReader(new InputStreamReader(ips));
			System.out.println("client said:"+br.readLine());


			//关闭各对象
			ips.close();
			ops.close();
			s.close();
			ss.close();
		} catch (IOException exception) {
			exception.printStackTrace();
		}
	}
}

4.demo:TcpClient

import java.net.*;
import java.io.*;

public class TcpClient {
	public static void main(String[] args) {
		try {
			//用地址标签创建通道,这里需要服务端先开启
			Socket s = new Socket(InetAddress.getByName("127.0.0.1"), 8001);

			//同一个通道,服务端的输出流就是客户端的输入流;服务端的输入流就是客户端的输出流
			//开启通道的输入流
			InputStream ips = s.getInputStream();
			BufferedReader brNet = new BufferedReader(new InputStreamReader(ips));

			//开启通道的输出流
			OutputStream ops = s.getOutputStream();
			//包装输出流
			DataOutputStream dos = new DataOutputStream(ops);

			//键盘录入信息
			//System.in是一个位流,InputStreamReader转换为字符流,然后再使用BufferedReader为其增加缓冲功能
			BufferedReader brKey = new BufferedReader(new InputStreamReader(System.in));
			while (true)
			{
				String strWord = brKey.readLine();
				//判断是否为换行,换行则表示结束
				if (strWord.equalsIgnoreCase("quit"))
				{
					break;
				}
				else
				{
					System.out.println("I want to send: " + strWord);
					//System.getProperty("line.separator")获取操作系统对应的换行符
					dos.writeBytes(strWord + System.getProperty("line.separator"));
					System.out.println("Server said: " + brNet.readLine());
				}

			}

			//关闭对象
			dos.close();
			brNet.close();
			brKey.close();
			s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

5.效果

相关文章

微信公众号

最新文章

更多