第78节:Java中的网络编程(上)
第78节:java中的网络编程(上)
前言
网络编程涉及ip,端口,协议,tcp和udp的了解,和对socket通信的网络细节.
网络编程
osi
开放系统互连
网络编程指io加网络
tcp/ip模型:
- 应用层
- 传输层
- 网际层
- 主机到网络层
osi模型:(封装) 网络1封包->网络2拆包
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
网络通讯要素:
- ip地址
- 端口号
- 传输协议
主机名和ip地址是对应的,默认的主机名:localhost
java.net 类 inetaddress java.lang.object -> java.net.inetaddress 已实现的接口: serializable 已知子类: inet4address, inet6address public class inetaddress extends object implements serializable 该类表示互联网协议ip地址
ip地址是ip使用32或128位无符号数字,它是一种低级的协议,udp和tcp协议都是在它的基础上构建的.
inetaddress的实例包含ip地址,相应的主机名
升级:
java.net 类 inet6address java.lang.object -> java.net.inetaddress -> java.net.inet6address 所有已实现的接口:serializable public final class inet6address extends inetaddress 该类表示互联网协议第6版地址
获取ip地址
package com.dashucoding.ip; import java.net.inetaddress; import java.net.unknownhostexception; public class ipdemo { public static void main(string[] args) throws unknownhostexception { // todo auto-generated method stub // ip地址对象 inetaddress // 获取本地主机地址对象 inetaddress ip = inetaddress.getlocalhost(); // 获取主机地址和主机名 system.out.println(ip.gethostaddress() + ":" + ip.gethostname()); inetaddress ip2 = inetaddress.getbyname("192.168.2.151"); // 获取主机地址和主机名 system.out.println(ip.gethostaddress() + ":" + ip.gethostname()); // 主机名是需要进行解析的 } }
域名解析_查表
c:\windows\system32\drivers\etc
dns
域名解析服务器,宽带服务.配置dns
域名服务器主机,一个网址浏览要到它的ip地址,要找到,就会把ip地址放到dns
域名解析服务器,供给本地使用宽带连接的使用,就可以在浏览器中找到ip地址,浏览网址了.
装dns
服务器软件,把你要浏览的地址ip写进去就可以了
有些软件需要进行注册序列号?
// hosts 文件配置 127.0.0.1 www.###.cn // 该域名地址
端口
端口,为物理端口,一台电脑发送信息给另一台电脑的软件,发送ip地址完, 要带上端口号, 然后 对应另一台接收消息的软件 有个软件应用程序的数字标识,为逻辑端口, 这样就可以对应发送到另一台电脑上的对应软件接收消息.
我今天要去一家酒店去了地址,到了楼层, 要知道哪个房间号,才知道对应做什么事.
传输协议
tcp和udp: 传输协议,传输规则,通讯规则,传输层.
udp
,不需要建立连接.我发给你信息,不管你在不在,我就发给你了.我送你东西,写个地址,发到你家就行.有个包,装东西,有大小限制,最多是64k的限制数据.(好处,速度快,不可靠)
tcp
发数据,要确保连接是不是畅通的.tcp
是通过三次握手完成的,确保数据的连接畅通.用流行的话语:
完成了三次tcp握手:
女朋友发给男朋友
:"在吗?"
男朋友回复女朋友
:"我在!"
女朋友回复男朋友
:"我知道了"
这样爱情可靠,但是很浪费时间的,这样维护情感有点耗时,但是很可靠.
tcp
断开就不传了,udp
不管.电话来形容tcp,对讲机来形容udp.
socket
socke <-> socket
数据在两者之间通过io传输,传输协议tcp或udp
socket就像两端插口,传输协议不一样,socket插口也是由不同的类型的.数据在两者之间进行传输,数据是基于网络的io流进行传输的,传输过程就是传入和传出的过程
udp_发送端_out
java.net class datagramsocket java.lang.object -> java.net.datagramsocket all implemented interfaces: closeable, autocloseable 已知直接子类: multicastsocket public class datagramsocket extends object implements closeable 该类为用于发送和接收数据报数据包的套接字,数据报套接字是分组传送服务的发送或接收点.
例子:
datagramsocket s = new datagramsocket(null); s.bind(new inetsocketaddress(8888)); datagramsocket s = new datagramsocket(8888);
构造方法摘要
方法 | 说明 |
---|---|
datagramsocket() |
构造数据报套接字并将其绑定到本地主机上的任何可用端口 |
datagramsocket(datagramsocketimpl impl) |
使用指定的datagramsocketimpl 创建一个未绑定的数据报套接字 |
datagramsocket(int port) |
构造数据报套接字并将其绑定到本地主机上的指定端口 |
datagramsocket(int port, inetaddress laddr) |
创建一个数据报套接字,绑定到指定的本地地址 |
datagramsocket(socketaddress bindaddr) |
创建一个数据报套接字,绑定到指定的本地套接字地址 |
receive(datagrampacket p)
:从此套接字接收数据报包send(datagrampacket p)
:从此套接字发送数据报包
java.net class datagrampacket java.lang.object -> java.net.datagrampacket public final class datagrampacket extends object 该类表示数据报包 将数据封装到数据包中,数据包对象为datagrampacket
数据包
datagrampacket(byte[] buf, int length) // 字节数组来的
构造一个datagrampacket
用于接收长度的数据包length
.
receive public void receive(datagrampacket p) throws ioexception 此套接字接收数据报包 返回, datagrampacket的缓冲区填充了接收的数据 数据报包也包含发送的ip地址和发送方的端口号
udpsend
package com.dashucoding.udp; import java.io.ioexception; import java.net.datagrampacket; import java.net.datagramsocket; import java.net.inetaddress; import java.net.socketexception; import java.net.unknownhostexception; public class udpsend { public static void main(string[] args) throws ioexception { system.out.println("udp 发送端 run"); // 先建立upd的socket 面向对象编程 // 将数据封装到数据包中 // 使用socket对象的send方法 // 将数据包发送出去 // 关闭资源 datagramsocket ds = new datagramsocket(); // 数据 string text = "我是发送端,发送的数据"; // 将数据转成字节数组 byte[] buf = text.getbytes(); // 将字节数据封装到数据包中 datagrampacket dp = new datagrampacket(buf, buf.length, inetaddress.getbyname("你的ip地址"),10000); // 发送 ds.send(dp); // 发完关掉,不然留着资源干嘛 ds.close(); } }
package com.dashucoding.udp; import java.io.ioexception; import java.net.datagrampacket; import java.net.datagramsocket; import java.net.socketexception; public class udprece { public static void main(string[] args) throws ioexception { system.out.println("udp 接收端 run"); // 定义udp接收数据,显示在屏幕上 // 先有插座嘛,udpsocket服务 // 接收数据前 -> 先将数据存储到数据包中 // 先定义数据包 // 数据包对象会获取数据包中的内容,发送端的ip和端口 // 关闭资源 // 有upsocket服务 datagramsocket ds = new datagramsocket(10000); // 接收数据,接收字节数据 byte[] buf = new byte[1024]; // 定义包 datagrampacket dp = new datagrampacket(buf, buf.length); // 还没存到数据包,进行存储 ds.receive(dp); // 阻塞 string ip = dp.getaddress().gethostaddress(); int port = dp.getport(); string text = new string(dp.getdata(),0,dp.getlength()); system.out.println(ip+" : "+port+" : "+text); // 关闭资源 ds.close(); } }
键盘录入
发送端:
package com.dashucoding.udp2; import java.io.bufferedreader; import java.io.ioexception; import java.io.inputstreamreader; import java.net.datagrampacket; import java.net.datagramsocket; import java.net.inetaddress; import java.net.socketexception; import java.net.unknownhostexception; public class udpsend2 { public static void main(string[] args) throws ioexception { // todo auto-generated method stub system.out.println("udp2 发送端 run"); datagramsocket ds = new datagramsocket(); // 数据来源于键盘录入 bufferedreader bufr = new bufferedreader(new inputstreamreader(system.in)); string line = null; while ((line = bufr.readline()) != null) { if("over".equals(line)) { break; } // 将数据转成字节数组 byte[] buf = line.getbytes(); // 将字节数据封装到数据包中 datagrampacket dp = new datagrampacket(buf, buf.length, inetaddress.getbyname("你的ip地址"), 10002); ds.send(dp); // 发完关掉,不然留着资源干嘛 } ds.close(); } }
接收端:
package com.dashucoding.udp2; import java.io.ioexception; import java.net.datagrampacket; import java.net.datagramsocket; import java.net.socketexception; public class udprece2 { public static void main(string[] args) throws ioexception { // 有upsocket服务 system.out.println("udp2 接收端 run"); datagramsocket ds = new datagramsocket(10002); while (true) { // 接收数据,接收字节数据 byte[] buf = new byte[1024]; // 定义包 datagrampacket dp = new datagrampacket(buf, buf.length); // 还没存到数据包,进行存储 ds.receive(dp); // 阻塞 string ip = dp.getaddress().gethostaddress(); int port = dp.getport(); string text = new string(dp.getdata(), 0, dp.getlength()); system.out.println(ip + " : " + port + " : " + text); // 关闭资源 } // ds.close(); } }
群聊工程
变化ip地址192.168.1.255
tcp
socket() 通过系统默认类型的socketimpl创建未连接套接字 socket(inetaddress address, int port) 创建一个流套接字并将其连接到指定ip地址的指定端口 socket(string host, int port) 创建一个流套接字并将其连接到指定主机上的指定端口号 getoutputstream() 返回此套接字的输出流
网络编程_tcp_服务端
package com.dashucoding.tcp; import java.io.ioexception; import java.io.outputstream; import java.net.socket; import java.net.unknownhostexception; public class tcpclient { public static void main(string[] args) throws unknownhostexception, ioexception { // todo auto-generated method stub // 建立tcp的客户端socket 明确服务端的地址和端口 // socket io流 // 获取socket流 system.out.println("客户端运行"); // 建立tcp的客户端socket,明确服务端的地址和端口 socket s = new socket("ip地址",20003); // socket输出流数据发送 outputstream out = s.getoutputstream(); // 通过socket输出流将数据发送 out.write("hello tcp 来了".getbytes()); // 关闭 s.close(); } }
package com.dashucoding.tcp; import java.io.ioexception; import java.io.inputstream; import java.net.serversocket; import java.net.socket; public class tcpserver { public static void main(string[] args) throws ioexception { // todo auto-generated method stub // 获取客户端的数据,在屏幕上 // 思路 // 创建服务端的socket,明确端口,监听一个端口 // 服务端只要获取到链接过来的客户端就可以和指定的客户端通信了 // 通过获取客户端的读取流对象读取客户端发来的数据. // 显示屏幕上 system.out.println("服务端运行"); // 创建服务端的socket,明确接收端口 serversocket ss = new serversocket(20003); while (true) { // 服务端只要获取到连接过来的客户端就可以和指定的客户端通信 socket s = ss.accept(); string ip = s.getinetaddress().gethostaddress(); system.out.println(ip + "...connected"); // 通过获取客户端的读取流对象读取客户端发送来的数据 inputstream in = s.getinputstream(); // 流操作 byte[] buf = new byte[1024]; int len = in.read(buf); string text = new string(buf, 0, len); system.out.println(text); // 关闭 s.close(); } // ss.close(); } }
客户端和服务端交互
客户端:
package com.dashucoding.tcp2; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.net.socket; import java.net.unknownhostexception; public class tcpclient2 { public static void main(string[] args) throws unknownhostexception, ioexception { // todo auto-generated method stub // 实现客户端和服务端的收发过程 system.out.println("客户端2 启动"); // 创建客户端的socket对象 socket s = new socket("ip地址",20004); // 发送数据,通过socket输出流完成 outputstream out = s.getoutputstream(); out.write("服务端,我来了".getbytes()); // 读取服务端返回的数据,通过socket输入流 inputstream in = s.getinputstream(); byte[] buf=new byte[1024]; int len = in.read(buf); string text = new string(buf,0,len); system.out.println(text); // 关闭资源 s.close(); } }
服务端:
package com.dashucoding.tcp2; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.net.serversocket; import java.net.socket; public class tcpserver2 { public static void main(string[] args) throws ioexception { // todo auto-generated method stub system.out.println("服务端2 启动"); // 创建tcp服务端socket明确端口 serversocket ss = new serversocket(20004); while (true) { // 获取客户端 socket s = ss.accept(); system.out.println(s.getinetaddress().gethostaddress() + "..."); // 读取客户端的发送过来的数据 inputstream in = s.getinputstream(); byte[] buf = new byte[1024]; int len = in.read(buf); string text = new string(buf, 0, len); system.out.println(text); // 给客户端回馈数据 outputstream out = s.getoutputstream(); out.write("客户端,我已经收到".getbytes()); // 关闭客户端 s.close(); } // 关闭服务端 // ss.close(); } }
小结
网络编程到网络模型:一开始7层到4层
传输层的了解
网络通讯:
- ip:用于网络中主机的数字标识
- 端口:用于应用程序的数字标识
- 传输协议:用于数据传输的规则
tcp和udp的区别
tcp: 面向连接,三次握手,速度慢,可靠
udp: 面向无连接,速度快,不可靠
实现udp的通信:
可以发送,又可以接收 datagramsocket datagrampacket 数据包对象
实现tcp传输:
客户端,服务端
客户端要明确服务端的ip+端口,而服务端要明确端口,通过accept的方法获取客户端对象.
结言
那么你是否掌握了,什么是tcp和udp,socket通信机制,以及ip,端口,协议.
达叔小生:往后余生,唯独有你
you and me, we are family !
90后帅气小伙,良好的开发习惯;独立思考的能力;主动并且善于沟通
简书博客: 达叔小生
结语
- 下面我将继续对 其他知识 深入讲解 ,有兴趣可以继续关注
- 小礼物走一走 or 点赞
上一篇: 7nm Radeon VII终有非公版:迪兰一口气上四款
下一篇: 以前上班时