------- android培训、java培训、期待与您交流! ----------
网络通讯的要素
1. 要和哪个机子进行通讯。
这个机子一定要有个标识,也就是ip地址,也就是起个名字。
2. 数据要发送到对方指定的应用程序上。因为有很多的应用程序。
避免发生错误。为了标识这些应用程序,所以给这些网络应用程序都用数字
进行了标识。也就是把这些标志叫做端口(逻辑端口)。(0~65535)
3. 定义通信规则。也就是交流的语言,便于双方都能明白各自所说的话。
这个通讯规则成为协议。也就是定义了一门语言。也就是你发的数据我能明白。
国际组织就定义了通用的协议TCP/IP(UDP)。也就是使用这个规则去简析数据。当然可以使用其他规则,这必须要求和你通讯的机子也使用这个规则。
网络模型:为了在各自所需要实现的功能作出划分。使用分层的思想用于划分。每一个层次都有自己想要做的事情。也就是需要识别某些作用。如封装某些端口号。如确定使用TCP还是UDP协议。
网络层给了数据一个IP地址。也就是数据要去哪里。
也就是一个原始数据经过层层包装之后,从物理链路中传输出去。
网络编程在传输层和网际层。而javaweb在应用层,应用层通过网际层去传输数据,如使用浏览器。应用层将传输层和网际层封装好了,所以更加的简单。
传输层最常用的就是TCP和UDP,而网际层最常常使用的是IP。而应用层使用的是HTTP协议。
在Java语言中这三个要素如何表现。
通常要提供一些类。
IP对象类。InetAddress
端口:就是一个数字,没有必要封装成对象。
传输协议:十分的重要
UDP(将数据及源和目的封装成数据包中)
面向无连接的。把数据打成包,就是发,不管接收方是否存在。
在就收到,不在就丢掉,不需要建立连接。随度块。
步骤:
1. 将原始数据打成UDP数据包。
2. 指定一个地址,也就是UDP数据包去哪里(也就是对方的地址和端口要明确出来)。
特点:面向无 连接,包的大小有限制。大数据分成多个包去发。
不可靠。速度快,不需要建立连接。
TCP
面向连接的。也就是要想通信,对方必须在,必须先确认对方在。才能连接。
使用三次握手,来确定对方在。
特点:可靠,效率比较低。大数据量可以传输。而不用封装成包。 将数据一直发送到通路里。
上述两种协议在java中提供了类去直接使用
首先看一个比较重要的类。
Socket
套接字是两台机器间通信的端点。
也就是两个要通讯的两个点的表示。
也就是qq----qq进行通讯,qq也就是Socket通讯的端点。
相当于一个网络应用程序。也就是Socket,这个端点的数据经计算机去处理。
通讯的两端必须都有Socket,网络通信也就是Socket间的通讯。
数据在两个Socket间通过IO传输。
由于传输协议不同(UDP/TCP),所以每个传输协议都有自己不同的建立端点的方式。也就是建立Socket的方式
就有了UDP特有的传输方式所对应的对象。
建立UDP的Socket端口。
有两个类。DatagramSocket
此类表示用来发送和接收数据报包的套接字。
该类中具有发送方法
voidsend(DatagramPacket p); 从此套接字发送数据报包。
voidreceive(DatagramPacket p) ;从此套接字接收数据报包。
原始数据在封装成包发送时候,必须要有对方和自己的发送地址和端口。
都要封装成一个数据包,java提供了这个数据包用来封装数据。
DatagramPacket 这个类既能发送数据(必须增加地址),也能接收数据。
使用不同的构造方法。
一定要记住网络编程的流程。
1. 建立UDP特定的Socket服务,建立端点,没有端点不行。
2. 确定要发送的数据,提供数据,并封装到数据包(封装了目的地址和端口)。
3. 通过Socket服务的发送功能将数据包发送出去。
4. 关闭资源
//1,创建UDP服务,通过DatagramSocket对象
DatagramSocket ds = new DatagramSocket();
//2,确定数据,并封装成数据包
byte[] bytes = "woaini".getBytes();
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,InetAddress.getByName("192.168.1.254"),10000);
//3,通过Socket服务,将已有的数据包发送出去,通过send方法
ds.send(dp);
//4,关闭资源
ds.close();
基本创建流程如上。凡是涉及网络数据传输,必使用数据流。
在接收端接收的步骤:
1. 定义UdpSocket服务,通常会监听一个端口,其实就是给这个接收网络应用程序定义数字标识,方便于明确那些数据过来可以处理。
2. 定义一个数据包,因为要存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3. 通过Socket服务的receive方法将受到的数据存入到已定义好的数据包中。
4. 通过数据包对象的特有功能,将这些不同的数据取出。打印在控制台上。
class UdpReceive
{
public static void main(String[] args) throws Exception
{
//1,创建UDPSocket端点。并指定其接收端口
DatagramSocket ds = new DatagramSocket(10000);
//2,定义数据包,用于存储数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3,通过端点的receive方法将收到的数据存入数据包中
ds.receive(dp);//receive为阻塞式方法,没有数据就一致在那里等。知道数据传输过来。
//4,通过数据包的方法获取其中的数据。
String ip = dp.getAddress().toString();
//ip
String data = new String(dp.getData(),0,dp.getLength());
//data数据
int port = dp.getPort();
//端口
System.out.println(ip+"..."+data+"..."+port);
ds.close();
}
}
输出:/127.0.0.1...woaini...53841(后边这个值是系统随机给出发送端的端口号)
/*
编写一个聊天程序。
有收数据部分,和发送数据部分。
这两部分需要同时执行。
就用到了多线程技术。
一个线程控制接收,一个线程控制发送。
因为接收和发送的动作是不一致的,所以要定义两个run方法。而且这俩个方法要封装到不同的类中。
*/
import java.net.*;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.io.*;
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
Scanner sc = new Scanner(System.in);
String line = null;
while((line = sc.nextLine())!=null)
{
if(line.equals("886"))
{
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10002);
ds.send(dp);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
class Rece implements Runnable
{
private DatagramSocket ds;
public Rece(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(data);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
public class Chat
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendDs = new DatagramSocket();
DatagramSocket receiveDs = new DatagramSocket(10002);
ExecutorService es = Executors.newCachedThreadPool();
es.execute(new Send(sendDs));
es.execute(new Rece(receiveDs));
}
}