——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
一.IP地址、端口号、传输协议
1、IP地址用于唯一的标识通信中的一个网络实体,这个通信实体既可以是一台主机,或者一台打印机,也可以是路由器的某一个端口。在基于IP协议通信中传输的数据包都必须经过IP地址的标识。
IP是个32位(32bit)整数,通常为了便于记忆,把它分成4个8位的二进制数,每个8位用圆点分开,每个8位可以转换成一个0~255的十进制整数。如:255.255.255.0
本地回环地址:127.0.0.1
2、数据要发送到指定的应用程序上。为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。为了方便称呼这个数字,叫做端口,逻辑端口。
端口是个16位的整数,用于表示将数据交给哪个应用数据处理,因此,端口是应用程序和外界交换数据的出入口,它是一种抽象的软件结构,包括一些数据结构和IO的缓冲区。用0~65535来表示福安口号。不同的应用程序处理不同端口上的数据。
如图:OSI参考模型和TCP/IP参考模型
同一台机器上不能有2个应用程序使用同一个端口。0~1024端口,一般被系统所保留。
3、定义通信规则。这个通信规则称为协议。国际组织定义了通用协议TCP/IP协议。常见的有TCP和UDP
二.Socket
Socket就是为网络服务提供的一种机制。通信的两端都有Socket。网络通信其实就是Socket之间的通信。数据在两个Sodket之间通过IO传输。
三.InetAddress类
作用:InetAddress来代表IP地址。
InetAddress类没有提供构造器。提供了两个静态方法来获取InetAddress实例对象。
getByName(String host):根据主机获取对应的Address对象。
getByAddress(Byte[] addr):通过原始地址来获取Address对象。
获取InetAddress对象对应的ip地址和主机名。
String getCanonicalHostName():获得此IP地址的全限定域名。
String getHostAddress():返回该InetAdress实例对应的字符串IP地址。
String getHostName():获得此IP地址的主机名。
getLocalHost():获取本机IP地址对应的InetAddress对应的实例。
isReachable():测试是否可达该IP地址。
四.UDP传输:
java使用DatagramSocket代表UDP协议的Socket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,它的唯一作用就是接收和发送数据包。java使用DatagramPacket代表数据包,DatagramSocket接收和发送的数据都是通过DatagramPacket完成的。DatagramSocket构造器。
DatagramSocket():创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址,本机的所有可用端口中随机的选择某个端口。
DatagramSocket(int port):创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址,指定端口。
DatagramSocket(int port,InetAddress Iaddr):创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址,指定端口,指定IP地址。
实例:定义udp发送端。
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UdpDemo {
public static void main(String[] args)throws Exception{
//1、建立服务。
DatagramSocket ds = new DatagramSocket();
//2、确定数据类型,将数据封装成包。
byte[] buf = "udp ge men lai le".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.100"),10000);
//3、发送数据。
ds.send(dp);
//4、关闭服务。
ds.close();
}
练习:
/*定义udp的接收端。
思路:
1,定义一个数据包,因为要存储接收到的字节数据。因为数据包对象中有更多的功能可以提取字节数据中的不同数据信息。
2,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
3,通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。
4,关闭资源。
注意:定义udpsocket服务,通常会监听一个端口,其实就是接收网络应用程序定义数字标识,方便应用程序可以处理。
*/
class UdpRece {
public static void main(String[] args)throws Exception{
//1,创建udp socket,建立端点。
DatagramSocket ds = new DatagramSocket(10000);
// 2,创建数据包,用于存储数据。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
// 3,通过服务的receive方法将接收到的数据存入数据包。
ds.receive(dp);
// 4,通过数据包中的方法将接收到的数据取出。
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
int port = dp.getPort();
System.out.println(ip + "::"+data + "::" + port);
// 5,关闭资源。
ds.close();
}
}
练习:
/*局域网聊天程序*/
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.UnknownHostException;
import java.lang.Thread;
class Send implements Runnable{
//由于不知道用哪个方法,故定义成构造器。
private DatagramSocket ds;
public Send(DatagramSocket ds){
this.ds = ds;
}
//Runnable子类中的run方法覆盖了Runnable的抽象run方法
public void run(){
try {
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=bufr.readLine())!=null){
if("886".equals(line)){
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp =
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.100"),10002);
ds.send(dp);
}
ds.close();
}
catch (UnknownHostException e) {
e.printStackTrace();
} 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[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println(ip + "::" + data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ChatDemo {
public static void main(String[] args)throws Exception {
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10002);
//传入Runnable的子类对象
new Thread(new Send(sendSocket)).start();
new Thread(new Rece(receSocket)).start();
}
}
TCP传输练习:
package day23;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
class TcpClient{
public static void main(String[] args)throws Exception{
//创建客户端的Socket服务,指定目的主机和端口
Socket s = new Socket("192.168.0.100",10003);
//为了发送数据,应该获取Socket中的输出流
OutputStream out = s.getOutputStream();
out.write("ge men lai le".getBytes());
s.close();
}
}
class TcpServer{
public static void main(String[] args){
//创建服务端服务,并监听一个端口
ServerSocket ss = new ServerSocket(10003);
//通过accept方法回去连接过来的客户端对象。
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);
}
}
public class TcpDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-