黑马程序员-java 网络编程

----------- android培训java培训、java学习型技术博客、期待与您交流! ------------ 

 

对于网络编程,首先我们需要知道的是,网络的通讯(数据交互)的原理:

比如,两台电脑直接进行信息交互:

1.首先要知道对方的IP地址或者主机名称,简单来说就是:要知道它在那里?

2.数据发送到对方指定的应用程序上(比如:QQmsn两个程序,你到底要发给谁?所以需要指定),为了标识这些应用程序,所以给这些网络应用程序都使用数字进行标识,为了方便称呼这个数字,称之为端口,这个是指的逻辑端口。简单来说就是:要知道发给谁?

3.  知道了需要和那个应用程序进行信息交互,而在通讯过程中,定义了对应的通讯规则,称之为协议。国际组织定义的通用协议是ICPIP。简单来说就是:我们直接使用什么交流规则,比如:使用手语或者口语。

 

说了这么多,那么网络编程的目的是什么?

就是指直接或间接地通过网络协议与其他计算机进行通信。

 

那么根据上面的信息,我们可以知道网络通讯的要素有:

1. IP地址:ip地址是数字型的,用来标识网络中的某个设备,其中:IPV432位,IPV6128      

2. 端口号:端口是一个16位的整数,用于表示数据提交给那个通信程序处理。因此,端口就是应用程序与外界交流的出入口,所以同一台机器上不能有两个程序使用同一个端口,有效端口:0~65535 ,其中0~1024是系统使用或者保留端口。

3. 传输协议:通讯之间的规则,常见协议是:TCP/UDP

 

而对应网络通讯,我们按照通讯层次,定出了对应的网络模型:

1.OSI参考模型:

分为:应用层,表示层,会话层,传输层,网络层,数据链接层和物理层

2.TCP/IP参考模型

分为:

应用层:包含了OSI参考模型的应用层,表示层,会话层, 这层中常见HTTP/FTP协议

传输层:这层中常见TCP/UDP协议

网际层:这层中常见IP协议

主机至网络层:包含了OSI参考模型的数据链接层和物理层

 

如何获取对应的IP信息,,在Java中,提供了InetAdress类。

创建InetAdress的实例方式:

注:InetAddress类没有提供构造函数

1.getByName(String host):根据主机获取对应的InetAddress对象。

2.getByAddress(byte[] addr):根据原始IP地址来获取对应的InetAddress对象。

 

InetAdress提供获取对应的IP地址和主机名的方法:

1.String  getCannonicalHostName():获取此IP地址的全限定域名。

2.String  getHostAddress():返回该InetAddress实例对应的IP地址字符串。

3.String  getHostName():获取此IP地址的主机名。

 

实例:

import java.net.*;

publicclass  IPDemo{

    publicstaticvoid main(String[] args) throws Exception

    {

       //获取本地IP信息

       InetAddress i = InetAddress.getLocalHost();

       System.out.println(i.toString());

       System.out.println("address:"+i.getHostAddress());

       System.out.println("name:"+i.getHostName());

 

       //根据主机名获取InetAddress实例   

       InetAddress ia_baidu = InetAddress.getByName("www.baidu.com");   

       System.out.println("InetAddress:" + ia_baidu.getHostAddress());  

       //根据IP地址获取InetAddress实例   

       InetAddress ia_1 = InetAddress.getByAddress(newbyte[] {127, 0, 0, 1});  

       System.out.println(ia_1.getCanonicalHostName());

    }

} 

那么对于网络通讯协议,常见的有:

TCP:是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方各有一个socket,两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket(client socket)可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作,这个过程类似于生活中的打电话。

UDP:是一种无连接的协议,也不进行差错及流量的控制。因此UDP提供的服务是不可靠的,基于UDP的应用程序可根据情况自己承担可靠性方面的工作。

TCP/UDP区别:

UDP

将数据及源和目的封装成数据包中,不需要建立连接.

每个数据包的大小限制在64K以内,

因无连接,是不可靠协议.

不需要建立连接,速度快

TCP:

建立连接,形成传输数据的通道.

在连接中进行大数据量传输,通过三次握手完成连接,是可靠协议.

必须建立连接,效率会稍低

 

上面需要注意的是:

三次握手连接什么意思?

比如两个人进行问候。

甲:你吃了么?      相当于第一次握手,发送一个请求。

乙:我吃了!        相当于第二次握手,接受请求,并且进行应答,并且返回一个状态

甲:呃,我知道了。  相当于第三次握手,接受返回状态。

 

那么在Java中,TCP/UDP是怎么进行实现的呢?

一,UDP

由于是通讯过程,那么就会分为发送端和接收端

1)、发送端

要求:通过udp传输方式,将一段文字数据发送出去

步骤:

1.建立udpsocket服务

2.提供数据,将数据封装到数据包中

3.通过socket服务的发送功能,将数据包发出去

4.关闭资源

例如:

publicstaticvoid udpSend () throws Exception {

       DatagramSocket ds = new DatagramSocket();// 创建了udp的Socket服务

       byte[] arr = "Udp message come to!".getBytes();// 创建数据源

       // 建立数据抱包对象,并确认发送数据,长度.以及发送源,以及端口.

       DatagramPacket dp = new DatagramPacket(arr, arr.length, InetAddress.getByName("192.168.241.1"), 4000);

       ds.send(dp);// 发送数据

       ds.close();// 关闭socket服务

 }

2)、接收端

要求:定义一个应用程序,用于接收udp协议传输的数据并处理

步骤:

1. 定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识。方便于明确哪些数据过来该应用程序可以处理

2.定义一个数据包,因为要存储接收到的字节数据。数据包对象中提供了可以提取字节数据中不同数据信息的功能

3.通过socket服务的receive方法将接收到的数据存入已定义好的数据包中

4.通过数据包对象的特有功能,将不同的数据取出,打印在控制台上

5.关闭资源

例如:

publicstaticvoid udpGet() throws Exception {

       //创建socket服务,并定义固定端口

       DatagramSocket ds = new DatagramSocket(4000);

       byte[] arr = newbyte[1024];

       DatagramPacket dp = new DatagramPacket(arr, arr.length);

       ds.receive(dp);

       //获取数据

       String data = new String(dp.getData(), 0, dp.getLength());

       //获取ip

       String ip = dp.getAddress().getHostAddress();

       //获取端口号

       int port = dp.getPort();

       System.out.println(ip+":"+data+":"+port);

       ds.close();

}

小技巧:

要是一直开着接收发送端发送数据,那么可以通过使用循环方法,一直接收数据。

拓展,小程序模拟聊天程序

/*

有收数据的部分,和发数据的部分。

这两部分需要同时执行。

那就需要用到多线程技术。

一个线程控制收,一个线程控制发。

 

因为收和发动作是不一致的,所以要定义两个run方法。

而且这两个方法要封装到不同的类中。

*/

import java.io.*;

import java.net.*;

class Send implements Runnable

{

    private DatagramSocket ds;

    public Send(DatagramSocket ds)

    {

       this.ds = ds;

    }

    publicvoid run()

    {

       try

       {

           BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

           String line = null;

           while((line=bufr.readLine())!=null)

           {

              byte[] buf = line.getBytes();

              DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.103"),10023);

              ds.send(dp);

              if("886".equals(line))

                  break;

           }

       }

       catch (Exception e){

           thrownew RuntimeException("发送端失败");

       }

    }

}

 

class Rece implements Runnable{

    private DatagramSocket ds;

    public Rece(DatagramSocket ds){

       this.ds = ds;

    }

    publicvoid run()

    {

       try

       {

           while(true)

           {

              byte[] buf = newbyte[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());

              if("886".equals(data)){

                  System.out.println(ip+"....离开聊天室");

                  break;

              }

              System.out.println(ip+":"+data);

           }

       }

       catch (Exception e)

       {

           thrownew RuntimeException("接收端失败");

       }

    }

}

 

class  ChatDemo{

    publicstaticvoid main(String[] args) throws Exception

    {

       DatagramSocket sendSocket = new DatagramSocket();

       DatagramSocket receSocket = new DatagramSocket(10023);

 

       new Thread(new Send(sendSocket)).start();

       new Thread(new Rece(receSocket)).start();

 

    }

} 

二,TCP

TCP传输数据,分为客户端和服务端

客户端对应的对象是Socket

服务端对应的对象是ServerSocket

建立连接后,通过Socket中的IO流进行数据的传输.最后关闭socket客户端.

关闭服务端是可选操作

1)、客户端

需求:给服务端发送给一个文本数据。

步骤:

1.创建Socket服务。并指定要连接的主机和端口。

2.建立连接成功后,通过Socket中的IO流进行数据传输

例如:

import java.io.*;

import java.net.*;

class  TcpClient{

    publicstaticvoid main(String[] args) throws Exception 

    {

       //创建客户端的socket服务。指定目的主机和端口

       Socket s = new Socket("192.168.1.103",10034);

       //为了发送数据,应该获取socket流中的输出流。

       OutputStream out = s.getOutputStream();

       out.write("tcp,hello!".getBytes());

       s.close();

    }

} 

2)、服务端

需求:定义端点接收数据并打印在控制台上。

步骤:

1,建立服务端的socket服务。ServerSocket();

       并监听一个端口。

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

       通过ServerSokcet accept方法。没有连接就会等,所以这个方法阻塞式的。

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

       并打印在控制台。

4,关闭服务端。(可选)

例如:

class  TcpServer{

    publicstaticvoid main(String[] args) throws Exception{

       //建立服务端socket服务。并监听一个端口。

       ServerSocket ss = new ServerSocket(10034);

       //通过accept方法获取连接过来的客户端对象。

       while(true){

       Socket s = ss.accept();

       String ip = s.getInetAddress().getHostAddress();

       System.out.println(ip+".....connected");

       //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。

       InputStream in = s.getInputStream();

       byte[] buf = newbyte[1024];

       int len = in.read(buf);

       System.out.println(new String(buf,0,len));

       s.close();//关闭客户端.

       }

       //ss.close();

    }

}

拓展,小程序演示tcp的传输的客户端和服务端的互访

import java.io.*;

import java.net.*;

/*

演示tcp的传输的客户端和服务端的互访。

需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。

*/

/*

客户端:

1,建立socket服务。指定要连接主机和端口。

2,获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。

3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印。

4,关闭客户端资源。

*/

class TcpClient2{

    publicstaticvoid main(String[] args)throws Exception{

       Socket s = new Socket("192.168.1.254",10004);

       OutputStream out = s.getOutputStream();

       out.write("服务端,你好".getBytes());

       InputStream in = s.getInputStream();

       byte[] buf = newbyte[1024];

       int len = in.read(buf);

       System.out.println(new String(buf,0,len));

       s.close();

    }

}

class TcpServer2{

    publicstaticvoid main(String[] args) throws Exception{

       ServerSocket ss = new ServerSocket(10004);

       Socket s = ss.accept();

       String ip = s.getInetAddress().getHostAddress();

       System.out.println(ip+"....connected");

       InputStream in = s.getInputStream();

 
       byte[] buf = newbyte[1024];

       int len = in.read(buf); 

       System.out.println(new String(buf,0,len));

       OutputStream out = s.getOutputStream();

       Thread.sleep(10000);

       out.write("哥们收到,你也好".getBytes());

       s.close();

       ss.close();

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值