黑马程序员----Java网络编程

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

IP是互联网上的每一台计算机都有得一个唯一表示自己的标记。
IP地址使用4个8位的二进制数据表示,每8位之间使用圆点隔开,每个8位整数可以转换成一个0~255的十进制整数,因此我们一般看到的IP地址类似:192.168.1.1
分类:
IPv4:32位,分4段,0~255之间的十进制表示
IPv6:128位,分8段,0000~FFFF的十六进制数值,冒号分割。

java中InetAddress类要来表示IP地址,有两个子类:
Inet4Address(IPv4)
Inet6Address(IPv6)
常用方法

public static InnetAddress getByName(String host):根据主机获取对应的InetAddress对象
public static InnetAddress getLocalHost():根据本机过得InetAddress对象
public static InetAddress getByAddress(byte[] addr):根据原始Ip获得InetAddress对象
public String getHostName():得到IP地址
public boolean isReachable(int timeout):判断地址是否可以到达,同时指定超时时间

实例代码:

package xia.wt.net;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressDemo {

    public static void main(String[] args) throws IOException {
    //获得百度的InetAddress
        InetAddress  iad = InetAddress.getByName("www.baidu.com");
    //获得百度的InetAddress
        byte[] ip = new byte[]{(byte)180,97,33,107};
        InetAddress  iadd = InetAddress.getByAddress(ip);
    //获得本地InetAddress
        InetAddress  localiad = InetAddress.getLocalHost();

        System.out.println(iad);
        System.out.println(iadd);
        System.out.println(localiad);
    //检测是否可以到达百度主机//如果可以获得权限,则典型实现将使用 ICMP ECHO REQUEST;否则它将试图在目标主机的端口 7 (Echo) 上建立 TCP 连接。可能此方式被百度防火墙拦截,一只显示连接不上
            System.out.println(iad.isReachable(1000000));

    }
}

/**输出结果
www.baidu.com/180.97.33.107
/180.97.33.107
TL-WR745N/192.168.1.107
false
*/

URL(Uniform Resource Locator)统一资源定位符,可以直接使用此类找到互联网上的资源如一个简单的网页。
一般由:协议名,资源所在主机,端口,资源名等部分组成。
常用构造方法:

URL(String spec):根据指定的地址实例化URL对象;
URL(String protocol, String host, int port, String file) :实例化URL,并指定协议,主机,端口名字,资源文件
public URLConnection openConnection():得到URLConnection 对象
public final InputStream openStream():得到输入流

URLConnection封装访问远程网络资源一般方法的类,通过它可以建立与远程服务器的连接,检查远程资源的一些属性。

Java中URLEncoder可以为传递的内容编码,而URLDecoder可以为传递的内容解码;
URLEncoder:
public static String encode(String s,String enc):使用指定的编码机制将字符串转编码成application/x-www-form-urlencoded MIME字符串;
URLDecoder:
public static String decode(String s,String enc):使用指定编码机制对application/x-www-form-urlencoded MIME字符串解码

public class URLEncoderDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s ="原始文字";
        System.out.println(s);
        //将s进行utf-8编码
        s = URLEncoder.encode(s, "utf-8");
        System.out.println(s);
        //将s进行utf-8解码
        s=URLDecoder.decode(s, "utf-8");
        System.out.println(s);
    }
}

/**输出结果
原始文字
%E5%8E%9F%E5%A7%8B%E6%96%87%E5%AD%97
原始文字*/

TCP(Transmission Control Protocal)
是一种面向连接的、可靠的、基于字节流的传输层通信协议。
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元([1] MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体[1] 的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

Java中使用Socket实现TCP程序开发,使用此类可以方便的建立可靠的,双向的,持续的,点对点的通讯连接。
在Socket程序开发中,服务器端使用ServerScoket等待客户端的连接,在Java的网络程序中,每一个客户端都使用Socket对象表示。
在服务器端每次运行都要使用aceept()方法等待客户端连接,此方法执行之后服务器将进入阻塞状态,直到客户端连接之后程序才可以向下继续执行,此方法的返回类型是Socket,每一个Socket都表示每一个客户端连接对象。
Socket编程步骤:
1.建立网络连接;
2.打开连接到Socket的输入/输出流;
3.通过已打开的IO流进行读写操作;
4.关闭已打开的IO流和Socket;
示例代码:客户端和服务器端相互发送数据
客户端:

public class Client {

    public static void main(String[] args) throws UnknownHostException, IOException {
        //创建一个客户端对象
        Socket s = new Socket(InetAddress.getLocalHost(),11260);
        //准备输出、输入流
        OutputStream os  = s.getOutputStream();
        InputStream is = s.getInputStream();
        //像服务器发送数据
        os.write((Thread.currentThread().getName()+"客户端发来的消息").getBytes());
        byte[] bs = new byte[1024];
        int i = 0;
        i = is.read(bs);
        String str = new String(bs,0,i);
        System.out.println(str);
        //将接受到的数据返回给客户端
        os.write(str.getBytes());
        os.close();
        is.close();
        s.close();  
    }
}

服务器端:

public class Servers {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket对象并接受客户端发来的Socket对象
        ServerSocket ss = new ServerSocket(11260);
        Socket s = ss.accept();
        //获得输入、输出流
        InputStream is = s.getInputStream();
        OutputStream os = s.getOutputStream();
        //接受客户端发来的数据
        byte[] bs =new byte[1024];
        int i = 0;
        i=is.read(bs);
        String str = new String(bs,0,i);
        System.out.println(str);
        //像客户端送返回数据
        os.write((str+"Echo").getBytes());
        //再次接受客户端发来的数据
         i = is.read(bs);
        str = new String(bs,0,i);
        System.out.println(str);
        os.write((str+"Echo").getBytes());
        //通讯结束,关闭资源
        os.close();
        is.close();
        s.close();
        ss.close();
    }
}

一个ServerSocket在一个时间段内只能为一个Socket客户端提供服务,要想同时对多个Socket提供服务可以使用多线程。
实例代码:
服务端:

package xia.wt.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ThreadSocketSer {

    public static void main(String[] args) throws IOException {
        //创建服务器对象
        ServerSocket ss = new ServerSocket(8888);
        /*死循环接受客户端请求,没有客户端连接就一只阻塞主线程,
        有客户端连接就将就收到的客户端交给一个新线程处理,主线程继续等待客户端*/
        while(true){
            //接受客户端请求或阻塞在此处
            Socket s = ss.accept();
            //有客户端连接就交给新线程处理
            new Thread(new ThreadsServer(s)).start();;
        }
    }
}

class ThreadsServer implements Runnable{

    private Socket s;
    //接受主线程传来的客户端信息
    public ThreadsServer(Socket s){
        this.s = s;
    }

    @Override
    public void run() {
        try (//创建输入输出流
                BufferedReader  bf = new BufferedReader(new InputStreamReader(s.getInputStream()));
                PrintWriter pw  = new PrintWriter(s.getOutputStream(),true);
                ){
                boolean tag = true;
                while(tag){
                    //循环接受客户端数据并应答,直到客户端发送的数据是以5结尾
                    String s = bf.readLine();
                    if(s.endsWith("4")){tag=false;}
                    System.out.println(s);
                    pw.println(s+"--Echo+"+Thread.currentThread().getName());
            }

                bf.close();pw.close();s.close();
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }
}

客户端:

public class ThreadSocketCli{

    public static void main(String[] args) {
        //主线程创建5个线程,分别向服务端发送数据
        for(int j =0;j<5;j++){
            new Thread(new ThreadClient(),"线程"+j).start();

        }

    }
}


class ThreadClient implements Runnable{


    @Override
    public void run() {
        try(//创建客户端对象并创建输入输出流
                Socket s = new Socket(InetAddress.getLocalHost(),8888);
                PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                BufferedReader bf= new BufferedReader(new InputStreamReader(s.getInputStream()));
                ) {
            for (int i = 0; i < 5; i++) {
                //向服务端发送包含请求次数的数据
                pw.println(Thread.currentThread().getName()+"for"+i);
                //打印服务端返回的数据
                System.out.println(bf.readLine());
            }
            pw.close();
            bf.close();
            s.close();
        } catch (IOException e) {

            e.printStackTrace();
        }

    }
}

UDP(User Datagram Prptocol)

UDP协议全称是用户数据报协议 ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。

UDP开发中使用DatagramPacket包装一条要发送的信息,之后使用DatagramSocket完成发送操作。
实例代码
客户端向服务端发送数据
客户端:

public class UDPClient {
    public static void main(String[] args) throws IOException {
        //准备要发送的数据,并打包为DatagramPacket
        byte[] bs = "客户端发来的数据".getBytes();
        DatagramPacket dp=new DatagramPacket(bs,bs.length,InetAddress.getLocalHost(),8888);
        //发送数据
        DatagramSocket da = new DatagramSocket(8080);
        da.send(dp);
    }

}

服务端:

public class UDPServer {
    public static void main(String[] args) throws IOException {
        //准备数据包,用于接受数据
        byte[] bs = new byte[1024];
        DatagramPacket dp =new DatagramPacket(bs,bs.length);
        //接受数据并打印
        DatagramSocket da = new DatagramSocket(8888);
        da.receive(dp);
        System.out.println(new String(bs,0,dp.getLength()));

    }

}

TCP & UDP简单对比
1。基于连接与无连接 ;
2。对系统资源的要求(TCP较多,UDP少) ;
3。UDP程序结构较简单 ;
4。流模式与数据报模式 ;
5。TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值