黑马程序员_毕向东_Java基础_DAY23-24_网络编程

----------- android培训java培训、期待与您交流! ------------

网络基础知识:

网络参考模型:


网际层最常见的协议:IP

传输层最常见的协议:TCP/UDP

应用层最常见的协议:http、ftp

网络通信原理图:

 

网络通讯要素:

IP地址:InetAddress

  网络中设备的标示

  不易记忆,可用主机名

  本地回环地址:127.0.0.1,主机名:localhost

主机号为0,表示本网络

主机号为255,表示IP多播

端口号:

  用于标示进程的逻辑地址,不同进程的标示

  有效端口:0~65535,其中0~1024为系统使用或保留端口

80是IE端口,8080是tomcat端口,mysql是3306端口

传输协议:

   通讯的规则

   常见协议:TCP,UDP

 

InetAddress:

java.lang.Object

  |- java.net.InetAddress

此类表示互联网协议 (IP) 地址。

 直接已知子类:

Inet4Address, Inet6Address

 InetAddress没有构造函数!

 static InetAddress getLocalHost()

static InetAddress getByName(String host)//可接受域名或机器名

static InetAddress[] getAllByName(Stringhost) //多服务器

static InetAddress getByAddress(byte[]addr)

static InetAddress getByAddress(Stringhost, byte[] addr)

  调用以上方法可能会抛出java.net.UnknownHostException

  byte[] getAddress()

 String getHostAddress()  //获取IP地址

 String getHostName()     //获取主机名,不一定能拿到

 String getCanonicalHostName()

  重要的两个方法:

getByName

getHostAddress

 getByName()方法可以使用ip地址或者域名

 

在获取百度的ip地址时,可能返回多个IP地址(服务器集群)

这时候使用:

static InetAddress[] getAllByName(Stringhost)

 

使用示例:

import java.net.InetAddress;
import java.net.UnknownHostException;
publicclass IPDemo{
 
    publicstaticvoid main(String[] args) throws UnknownHostException{
        //static InetAddress getLocalHost() 返回本地主机的IP地址对象InetAddress
        InetAddressinet=InetAddress.getLocalHost();
        System.out.println(inet.toString());
        //根据IP地址对象获得主机名
        System.out.println(inet.getHostName());
        //根据IP地址对象获得本机IP地址
        System.out.println(inet.getHostAddress());
       
        //static InetAddress getByName(String host) 根据主机名拿到任意一台主机的IP地址对象
        InetAddress[]in= InetAddress.getAllByName("www.baidu.com");
        /*如果IP地址和对应的主机名没有在网络上,请求主机能找到地址,但是解析不成功。
         * 那么其它主机名还是IP地址,以获得IP地址为主 */
        for(int i=0;i<in.length;i++){
        System.out.println(in[i].getHostName());
        System.out.println(in[i].getHostAddress());
        }
//        InetAddress in=InetAddress.getAllByName("www.baidu.com");
//        System.out.println(in.getHostName());//www.baidu.com
//        System.out.println(in.getHostAddress());
    }
}

 

TCP 与 UDP:

都是传输层协议

 UDP: User Datagram Protocol, 用户数据报协议 

面向无连接

数据封包(数据报)、64k以下

不可靠

速度快 

应用:即时视频传输、聊天软件

适用情景:传输数据有突发性,数据较短,并且对可靠性要求不大,使用这个协议。

 

TCP:Transmission Control Protocol, 传输控制协议

 面向连接,三次握手

适合大量连续数据传输

可靠

速度低

 

总结:

UDP:面向无连接,数据会被封包,包的体积有限制64kb,不可靠,速度快。如聊天,视频     会议,桌面共享。

TCP:面向连接,可靠的,建立通路后可以传输大数据量。如下载

  

Socket:

socket的英文原义是“孔”或“插座”。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。

 在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。

 Socket正如其英文原意那样,象一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。

 Socket就是为网络服务提供的一种机制。

 通信的两端都有socket。

网络通信其实就是socket间的通信。

数据在两个socket间通过io传输。

 Socket / ServerSocket --- 传输流

DatagramSocket / DatagramSocket  --- 传输DatagramPacket

 

UDP通信:

DatagramSocket / DatagramPacket

 DatagramSocket用来发送和接收数据报包的套接字,即能发送也能接收,即两端都用的它。

接收:

void receive(DatagramPacket p)

发送:

send(DatagramPacket p)

 发送和接收的都是数据报包,即要把发送和接收的数据都要封装到DatagramPacket对象中。

 DatagramPacket,数据报包对象。用来实现无连接包投递服务。

 使用while(true)循环来循环执行接收端,new接收端Socket对象时,不能放入循环中,否则会出现java.net.BindException,即端口被占用。

  

创建DatagramSocket服务

 使用构造器----

 DatagramSocket() 

 protected DatagramSocket(DatagramSocketImpl impl)

         创建带有指定 DatagramSocketImpl的未绑定数据报套接字。

 DatagramSocket(int port)

         创建数据报套接字并将其绑定到本地主机上的指定端口。

 DatagramSocket(int port, InetAddress laddr)

         创建数据报套接字,将其绑定到指定的本地地址。

 DatagramSocket(SocketAddress bindaddr)

         创建数据报套接字,将其绑定到指定的本地套接字地址。

 

创建数据报包:

使用构造器----创建时要区分用于接收还是用于发送。

 用于接收:

DatagramPacket(byte[] buf, int length)

DatagramPacket(byte[] buf, int offset, intlength)

 用于发送:

DatagramPacket(byte[] buf, int length,InetAddress address, int port)

DatagramPacket(byte[] buf, int offset, intlength, InetAddress address, int port)

DatagramPacket(byte[] buf, int length,SocketAddress address)

DatagramPacket(byte[] buf, int offset, intlength, SocketAddress address)

 

注意:无论接收还是发送,都要将数据放入byte数组中。

     创建DatagramPacket对象,一定要指定byte数组、长度、IP+port,偏移量随便

     IP地址要用InetAddress表示,而不能用String

 

接收和发送都要指定需要处理的byte数组中的长度和偏移量,在发送时还要指定要发送的目的地,用InetAddress+port或者SocketAddress来表示。

 DatagramPacket对象中封装了一些基本信息,可以使用get方法获取。

如:

获取源地址信息:

 InetAddress getAddress() 

 intgetPort()

 SocketAddress getSocketAddress()

 

获取数据信息:

 byte[] getData()

  intgetLength()

 intgetOffset()

  

UDP信息发送思路:

 1.建立DatagramSocket套接字

2.提供数据,将数据转为到byte[]中,并封装到DatagramPacket中,其中包含了目的地信息。

3.使用DatagramSocket的send方法发送数据报:send(DatagramPacket)

4.发送结束后,关闭资源,即使用DatagramSocket的close方法释放套接字,释放底层资源。

 

DatagramSocket ds = new DatagramSocket();//使用由系统分配的随机可用端口进行发送
byte[] buf = "我是信息".getBytes();
DatagramPacket dp =
       newDatagramPacket(buf, buf.length,InetAddress.getByName("192.168.1.254"), 10000);
ds.send(dp);
ds.close();


UDP信息接收思路:

 1.建立DatagramSocket套接字,并指定所监听的端口

2.定义一个数据包,用于接收字节数据,并获取其中的信息。

3.使用receive方法将接收到的数据存入已定义好的数据包中。

4.通过数据包对象的特有功能,获取其中的数据和信息。

5.关闭资源。

 

注意:receive方法是一个阻塞式方法

     在为DatagramSocket指定端口时,如果指定的端口被占用,则会抛出java.net.BindException,

     即绑定异常。端口不是即时释放的。

示例:

DatagramSocket ds = newDatagramSocket(10000); //监听10000端口
byte buf = new byte[1024 * 64];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
ds.receive(dp);
String ip =dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData(), 0,dp.getLength());
 
System.out.println(ip + ":" +port + "\n\t" + data);
ds.close();

 

练习:

//:UdpDemo.java
//简单的网络信息发送演示
 
import java.net.*;
 
class UdpSend
{
       publicstatic void main(String[] args) throws Exception
       {
 
              DatagramSocketsocket = new DatagramSocket(8888);
              byte[]message = "Hello, Udp".getBytes();
              DatagramPacketpacket = new DatagramPacket(message, message.length,InetAddress.getLocalHost(),
10000);
              socket.send(packet);
              socket.close();
       }
}
 
class UdpReceive
{
       publicstatic void main(String[] args) throws Exception{
              DatagramSocketsocket = new DatagramSocket(10000);
              byte[]buf = new byte[1024];
              DatagramPacketpacket = new DatagramPacket(buf, 1024);
              socket.receive(packet);
              Stringmessage = new String(packet.getData(), 0, packet.getLength());
              System.out.println(message);
              socket.close();
       }
}

 

//:UdpDemo2.java
//发送端从键盘循环录入数据,接收端逐条接收,输入over两端结束socket服务
 
import java.net.*;
import java.io.*;
 
class UdpSend2
{
       publicstatic void main(String[] args) throws Exception
       {
              DatagramSocketds = new DatagramSocket(10000);
              BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in));
              Stringmessage = null;
              while((message= br.readLine()) != null){
                     byte[] buf = message.getBytes();
                     ds.send(newDatagramPacket(buf, buf.length, InetAddress.getLocalHost(), 10001));
                     if("over".equalsIgnoreCase(message))
                            break;
              }
              br.close();
              ds.close();
       }
}
 
class UdpReceive2
{
       publicstatic void main(String[] args) throws Exception{
              DatagramSocketds = new DatagramSocket(10001);
              while(true){
                     byte[]buf = new byte[1024 * 64];
                     DatagramPacketdp = new DatagramPacket(buf, buf.length);
                     ds.receive(dp);
                     Stringip = dp.getAddress().getHostAddress();
                     intport = dp.getPort();
                     Stringmessage = new String(dp.getData(), 0, dp.getLength());
                     if("over".equalsIgnoreCase(message)){
                            ds.close();
                            break;
                     }
                     System.out.println(ip+ ":" + port + "\n" + message);
              }
       }
}

 

TCP通信:

Socket / ServerSocket 

建立客户端 / 服务器端

 Socket()

Socket(InetAddress address, int port)

Socket(String host, int port)

 Socket s = newSocket("192.168.1.254",10003);

//创建成功即代表连接建立成功

//连接建立成功后即创建了I/O流。

//即建立之后流就已经存在了

使用下列方法获取流

 InputStream getInputStream()

 OutputStream getOutputStream()

 

ServerSocket

 1.建立服务器端的socket服务

ServerSocket server = new Socket(10003);

 2.获取连接过来的客户端对象。

 Socket accept()

 此方法是阻塞式方法

 3.客户端如果发来数据,那么服务器端要使用对象的客户端对象,并获取到该客户端对象的读取流来读取数据。

 注意:

文本传输可以加 Buffered。

加了Buffered之后要记得刷新。

在使用readLine方法时,要注意换行。

 练习: 

//: TcpDemo.java
//简单的客户端与服务端通信演示
 
import java.net.*;
import java.io.*;
 
class TcpServer
{
       publicstatic void main(String[] args) throws Exception
       {
              ServerSocketss = new ServerSocket(10001);
              Socketsocket = ss.accept();
              InputStreamin = socket.getInputStream();
              byte[]buf = new byte[1024];
              intlen = in.read(buf);
             System.out.println(socket.getInetAddress().getHostAddress()+ ":" + socket.getPort() + "..." + new String(buf, 0,len));
 
              OutputStreamout = socket.getOutputStream();
              out.write("Hello,Client".getBytes());
              ss.close();
       }
}
 
class TcpClient
{
       publicstatic void main(String[] args) throws Exception{
              Sockets = new Socket(InetAddress.getLocalHost(), 10001);
              OutputStreamout = s.getOutputStream();
              out.write("Hello,Server".getBytes());
             
              InputStreamin = s.getInputStream();
              byte[]buf = new byte[1024];
              intlen = in.read(buf);
              System.out.println(InetAddress.getLocalHost()+ "..." + new String(buf, 0, len));
              s.close();
       }
}

 

//: TcpDemo2.java
//客户端通过键盘录入向服务器端发送文本信息,服务端返回其大写形式
 
import java.net.*;
import java.io.*;
 
class TcpServer2
{
       publicstatic void main(String[] args) throws Exception
       {
              ServerSocketss = new ServerSocket(10002);
              Sockets = ss.accept();
              InputStreamin = s.getInputStream();
              OutputStreamout = s.getOutputStream();
              byte[]buf = new byte[1024];
              intlen = 0;
              while((len= in.read(buf)) != -1){
                     Stringmessage = new String(buf, 0, len);
                     out.write(message.toUpperCase().getBytes());
              }
              //ss.close();
       }
}
 
class TcpClient2
{
       publicstatic void main(String[] args) throws Exception{
              Sockets = new Socket(InetAddress.getLocalHost(), 10002);
              OutputStreamout = s.getOutputStream();
              InputStreamin = s.getInputStream();
              BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in));
              Stringbuf = null;
              intlen = 0;
              byte[]buf2 = new byte[1024];
              while(!"over".equals((buf= br.readLine()))){
                     out.write(buf.getBytes());
 
                     len= in.read(buf2);
                     System.out.println(newString(buf2, 0, len));
              }
              s.close();
       }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值