java网络编程基础-传输层协议TCP&UDP
Posted Henrik-Yao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java网络编程基础-传输层协议TCP&UDP相关的知识,希望对你有一定的参考价值。
一.网络编程基础
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.效果
以上是关于java网络编程基础-传输层协议TCP&UDP的主要内容,如果未能解决你的问题,请参考以下文章