1…socket
网络通讯要素
l IP地址:InetAddress
• 网络中设备的标识
• 不易记忆,可用主机名
• 本地回环地址:127.0.0.1 主机名:localhost
l 端口号
• 用于标识进程的逻辑地址,不同进程的标识
• 有效端口:0~65535,其中0~1024系统使用或保留端口。
l 传输协议
• 通讯的规则
• 常见协议:TCP,UDP
2…TCP和UDP
l UDP
• 将数据及源和目的封装成数据包中,不需要建立连接
• 每个数据报的大小在限制在64k内
• 因无连接,是不可靠协议
• 不需要建立连接,速度快
l TCP
• 建立连接,形成传输数据的通道。
• 在连接中进行大数据量传输
• 通过三次握手完成连接,是可靠协议
• 必须建立连接,效率会稍低
UDP:
生活中例子:
UDP生活中相当于到邮局寄饼干,,,饼干就是那数据,你拿着数据就到邮局了这时邮局就给你一盒子把饼干放在盒子里面,放完后拿胶带把这个盒子封好,这就是封包,,UDP需要把数据打成一个数据包...打包完后你要发到哪里去你得告诉这包,所以你就在包上面贴了纸注明寄给谁,寄到哪里,就是对方的地址和端口要明确出来,比如春生大厦2000房间,然后这个包就发出去了,可是发这包的时候,,,那个对方的地址(大厦地址)不一定在,或者也可以说2000这端口不一定开着(比如说2000房间关门了那天公司休假),地址在但是公司没开门,所以你来了后我们处理不了,
TCP
面向连接:我们想通过tcp进行通讯的话对方必须在,我先去确定对方是否在,对方在我就进行数据的发送,,判断对方在不在是通过三次握手来完成的,,,通过三次握手完成tcp传输通道的建立
三次握手:第一次我说李四在吗,李四收到后回答说他在(第二次),我收到你的回答后我说李四我知道你在了(第三次),,,连接有了以后数据在这连接通道里传输就可以了,,
建立通道;第一次我发个信息说李四在吗你收到的话你会说你在,你就把信息返回给我,(这是第二次),,问题是我发过去你收到了但是你发给我,我收没收到你此时是不知道,所以我收到你的数据以后呢我再给你发一次说我知道你在了这是第三次,,
可靠:如果对方断开的话,我就不传了,,通道都没了传输就没意义
tcp相当于打电话;我拿起电话就拨号在和对方连接,要连接谁你要指定出来,一按那个绿色键就拨出去了,拨出去是在向对方发送连接请求,说我要连接你,要握手,然后我就拿起电话在等待对方接通,对方只要一拿起电话,连接通道就建立了,接下来我和对方说话,,这话的内容就是数据,,数据就在这条通路里面进行通讯,,,,,对方一挂断电话的话就不传输数据了
3…网络参考模型
网络在传输过程中,为了更细致的划分其每次传输层次所对应的那个功能不一样而有了层次的细致划分,,简单的说,网络传输时你是干这事的,我是干那事的,我们为了以便于区分它们都属于什么时候该干什么事的话就把它们按照层次的形式给他进行了一个比较细致的划分,每一个层次都有自己所做的事情
4…ip地址
net包中用于描述ip对象的是InetAddress
java.net.InetAddress 他没有构造函数,,这些对象都是很复杂的..里面的数据很多,,,封装成对象方便使用,事物只要复杂的话就给他封装起来,可以简化操作
方法:
static InetAddress getLocalHost() 返回一个本类对象InetAddress
返回本地主机。 获取本地主机,,返回本机的主机名和ip地址
String getHostAddress()
返回 IP 地址字符串(以文本表现形式)。 获取ip地址
String getHostName()
获取此 IP 地址的主机名。 获取主机名I
代码:
InetAddressi=InetAddress.getLocalHost(); //getLocalHost();这里要抛异常,,UnknownHostException未知主机异常,就是有可能你获取不到这主机或者ip地址本来就是无效的,所以你需要处理,
System.out.println(i.toString());
System.out.println("address:"+i.getHostAddress());
System.out.println("name:"+i.getHostName());
5.. Socket
网络编程指的就是Socket(插座)编程,,每一个应用程序都有一个类似于电脑机箱后面的网线插槽,,Socket也可以理解为码头或者电脑网线插槽,,
Socket就是为网络服务提供的一种机制。
通信的两端都先得有Socket。只要有了他,才能去进行连接.连接后你的数据才会有传输的通路,,就是说先得有码头,才会有船进行运输
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
Socket也可以理解为码头,2个码头想进行通讯怎么办,用船带着货物从这个码头到那个码头,想要进行通讯,先得有码头
6.。udp发送和接收
(1)...发送
有了Socket这个通讯端点后,但是传输协议不一样,所以每个传输协议都有自己不同的建立端点的方式,,比如军用和民用传输,,那么就有了udp传输的特有传输方式对应的对象
java.net.DatagramSocket 数据Socket,,DatagramSocket他既能发送又能接收,,就是你搞2个端点的话,2个端点都有DatagramSocket
此类表示用来发送和接收数据报包的套接字,,,套接字就是插座
udp用到的对象是DatagramSocket,,DatagramSocket他建立端点,建立完后就把数据发出去,所以这个DatagramSocket服务里面有发送和接收的动作(方法)
方法:
voidreceive(DatagramPacket p) 接收数据
从此套接字接收数据报包。
voidsend(DatagramPacket p) 发送数据,,发送什么东西你得指定一下,所以得传入DatagramPacket(数据包),,udp是要把数据封装成数据包发出去的,,数据包里面封装了实体数据,对方地址和端口,还有我自己的地址和端口,,,,
从此套接字发送数据报包。
代码(1)发送数据
public class UdpSend {
publicstatic void main(String[] args) throws IOException {
//1,创建udp服务。通过DatagramSocket对象。
DatagramSocketds = new DatagramSocket(); //创建服务有可能会出问题,所以得抛异常
//2,确定数据,并封装成数据包。DatagramPacket(byte[]buf, int length, InetAddress address, int port)
byte[]buf = "udp ge men lai le ".getBytes();
//把数据封装数据包,buf.length是说我把数组里的全部数据都发出去,如果只发送数组里2个数据的话就写2
DatagramPacketdp =
newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.101"),10000); //封装地址时也可能出问题,万一你地址写错了呢
//3,通过socket服务,将已有的数据包发送出去。通过send方法。
ds.send(dp);
//4,关闭资源。
ds.close();
}
(2)接收:
java.net.DatagramPacket DatagramPacket 既可以用来封装数据还可以接收数据
构造方法摘要
DatagramPacket(byte[] buf, int length)
构造DatagramPacket,用来接收长度为length 的数据包。
DatagramPacket(byte[] buf, int length,InetAddress address, int port) address对方主机地址,,port是对方端口,,byte[] buf是字节数组,你最终发送的数据都是字节数据,,length 是说你buf数组里面有那么多数据,,你要发送几个出去,,,port是说你准备把这数据发送到address主机里的哪个应用程序上,那个应用程序就是端口,随便指定一个端口,,就是你把数据发到对方以后,对方至少得有一个应用程序来处理这些数据
代码(2)接收数据
public class UdpRece {
publicstatic void main(String[] args) throws IOException {
//TODO Auto-generated method stub
//1,创建udp socket
DatagramSocketds = new DatagramSocket(10000); 指定一个端口,这里是监听一个端口
while(true)
{
//2,定义数据包。用于存储数据。
byte[]buf = new byte[1024]; //定义一个数组存储接收到的数据
DatagramPacketdp = new DatagramPacket(buf,buf.length); //buf.length是这个缓冲区里的空间我全使用用来装数据
//3,通过服务的receive方法将收到的数据存入数据包中。
ds.receive(dp);//阻塞式方法。这步一执行完,,dp里面就有数据了
//4,通过数据包的方法获取其中的数据。这些数据包括地址端口,具体数据内容
Stringip=dp.getAddress().getHostAddress(); //获取ip
Stringdata = new String(dp.getData(),0,dp.getLength()); //获取具体数据内容,,
//newString(dp.getData())他是把数组里的1024个元素全部变为字符串了
//而buf里面只装了一点数据,所以就截取buf的一部分,那部分就是有效数据
intport=dp.getPort();
System.out.println(ip+"::"+data+"::"+port);
}
//5,关闭资源
ds.close();
}
}
7…tcp发送和接收
udp也可以用于下载,,但是你得保证在线这样数据才不会丢失,,,他把数据分成多个小包下载
udp分的是发送端和接收端,,而tcp是客户端和服务器端
TCP传输:
Socket(客户端对象)和ServerSocket(服务器端对象)
建立客户端和服务器端 这2个端点建立完后就能进行通讯
建立连接后,通过Socket中的IO流进行数据的传输
关闭socket
同样,客户端与服务器端是两个独立的应用程序
1.tcp分客户端和服务端。
2,客户端对应的对象是Socket。
服务端对应的对象是ServerSocket。
客户端服务器端就是基于网络应用的一个程序,,浏览器就是个标准的客户端
网络架构:
C/S:Client/Server
客户端,服务端。
特点:
1,需要在客户端和服务端都需要按照编写的软件。
2,维护较麻烦。
好处:可以减轻服务端的压力,如网络游戏。
B/S:Browser/Server
浏览器 ,服务端。
1,客户端不用单独编写软件。
因为客户端用的就是浏览器。
2,对于软件升级,只要考虑服务端即可。
弊端:所有的程序都运行在服务端,客户端的浏览器毕竟解析能力较弱。对游戏等。
(1)客户端:
java.net.Socket 客户端
构造方法:
Socket(InetAddress address, int port) Socke一初始化就先去找那个对应的服务器端,
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。 参数是:要连接的ip地址和端口,说明客户端一建立就要去连服务器端,,因为你客户端建立的目的就是为了连接服务端,服务器端都不在,你都没连成功,你客户端还怎么通讯呀,,他们依赖的是他们建立完的那条通道来进行数据的传输,,所以Socke一初始化就先去找那个对应的服务器端,
Socket()
通过系统默认类型的SocketImpl 创建未连接套接字 ,这个你创建完 Socket()对象后他是没有任何连接的,你可以通过Socket的connect(SocketAddress endpoint) 方法去连接指定的服务器端
Socket(String host, int port)
创建一个流套接字并将其连接到指定主机上的指定端口号。 host是主机名或者ip
方法:
InputStream getInputStream()
返回此套接字的输入流。 获取socket流里面的输入流
OutputStream getOutputStream()
返回此套接字的输出流。)
代码;tcp传输数据..客户端
public class TcpClient {
publicstatic void main(String[] args) throws UnknownHostException, IOException {
//TODO Auto-generated method stub
//创建客户端的socket服务。指定目的主机和端口,,Socket s =new Socket这步成功的话通道就建立了,,通路一建立好了以后,就有了一个socket流
//主机名和端口都有可能会写错,,所以会抛异常
Sockets = new Socket("192.168.1.254",10003);
//为了发送数据,应该获取socket流中的输出流。
//数据有读有写,所以socket流里面既有输入流也有输出流,,
//Socket对象一建立成功,通路有了以后就可以拿到socket流里面的输入流或者输出流来完成对数据的操作
//在这条通路当中数据有来有往(我发给你,你再发给我),,那条通路有2条路,我这端往对方发走一条路(输出流),,对方往我这边发走另一条路(输入流),
//那输入流和输出流不需要new,因为你通路只要一建立,这个socket流就已经存在了你只要需要通过Socket流里面的方法拿到里面的输入流或者输出流,就能用这流对象了
//通路有了以后,流就有了
//这里使用字节流,因为网络传输,你传输什么样的数据都有可能,所以用字节流,
OutputStreamout = s.getOutputStream();
//把数据写出去,这个数据会写到这个输出流里,并随着网络发送到对应的主机上
out.write("tcpge men lai le ".getBytes());
s.close();
//注意这里不需要关闭out流,因为out流是通过Socket获取到的,,s.close()后Socket都没了那么out流就没了
}
服务器端:
java.net.ServerSocket
构造函数:
ServerSocket(int port) 指定端口
创建绑定到特定端口的服务器套接字。
ServerSocket()
创建非绑定服务器套接字。再使用bind(SocketAddress endpoint) 绑定指定的ip
方法:
voidbind(SocketAddress endpoint)
将 ServerSocket绑定到特定地址(IP 地址和端口号)。
Socket accept()
侦听并接受到此套接字的连接。获取连接过来的客户端对象
代码:
class TcpServer
{
publicstatic void main(String[] args) throws Exception
{
//建立服务端的socket服务。并监听一个端口。
ServerSocketss = new ServerSocket(10003);
//通过accept方法获取连接过来的客户端对象。服务器端没有流对象,,,服务器端做的是我要拿到客户端对象,,因为客户端有流对象,,服务器端拿客户端的流对象和客户端进 行通讯
Sockets = ss.accept();
//打印ip,说这数据是哪个客户端发过来的,我这里拿到了客户端对象Socket了,,Socket里面封装了ip地址,,,
//如果是udp的话获取ip是从数据包里面获取
//你只要一连接进来我先知道你是谁
Stringip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connected");
//获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。s.getInputStream()就是源,,这个源比较特殊,他不是键盘录入也不是文件,这个源是网络流,, 因为这个数据来自于对方机器,是我从网络里面读出来的
InputStreamin = s.getInputStream();
//创建缓冲区
byte[]buf = new byte[1024];
//把读取到的数据放到数组里
intlen = in.read(buf);
System.out.println(newString(buf,0,len));
s.close();//关闭客户端 (服务端有可能不关自己,,关闭客户端,,因为你跟我连着,,你拿完数据了你还跟我连着,就浪费我资源,,你只要跟我连接的时间超过了我设置的时间,我就自动把你断开) .这个服务器就只服务一次,,所以用完一次就可以关闭
ss.close();(可选操作,,说服务器只对外服务一次,服务完就结束
)
}
}
注意;上面的代码是客户端向服务器端发送了一次请求后,连接上了就发送一次数据完事了,,服务器就获取到客户端对象,之后打印了信息就完事了,服务器端没有返回信息,,服务器端还没有做返回动作,,就是客户端发送数据后,,,服务器接收到了数据打印了一次,,但是服务器没有再向客户端发送信息,,好比打电话,,我向对方说话后,,对方没有跟我说话