Java网络编程基础

一.概述

网络编程,意在编写和网络相关的代码,主要实现利用网络进行交互的程序,而不仅限于与本地的程序,数据,用户进行交互与信息传递。无论是什么语言的网络编程,无非是要解决以下两个问题
1. 定位
2. 传输
在网络中,不管你是服务端还是客户端,都只是对这个网络接口所具有的职能的一种称呼,在网络中抽象出来,他们都是点对点之间进行传输的两个点而已。所以我们暂且不谈什么客户端,服务端,只求如何利用这个网络进行信息的交互。

第一点:定位

在网络中如何定位一个点,其实也就是如何定位一个主机。IP地址。在主机中又是如何定位那个与我产生信息交互的程序呢?端口号。所以由IP地址加上端口号即可完成一个传输对象的定位。在Java语言中,则使用的是InetAddress类,来封装IP地址的。即在Java中InetAddress对象就代表了一个IP地址,你如果要操作InetAddress类就是在操作一个主机的IP。
创建一个IP地址,即InetAddress对象

InetAddress ip1 = InetAddress.getByName("www.csdn.com");

InetAddress对象只能通过静态方法获得,一般常用的是上面这个getByName()方法,参数为域名,还有一个方法为:

static InetAddress  getByAddress(byte[] addr)
Returns an InetAddress object given the raw IP address .

常用的方法还有:
1. getHostName() 返回域名
2. getHostAddress() 返回IP地址

另一个在主机中定位的则是端口号,标识这正在计算机上运行的进范围时0~65535,其中0~1023被预先定义了,一般使用靠后一些的,而端口号与IP地址的组合就成为了网络套接字(Socket)。所以网络编程又叫做Socket编程。意思就是程序与程序之间的通信要借助于Socket对象来实现定位与传输,接下来我们就进入对于Socket的编程。

Socket

随着C/S架构的普及,现在网络上基本上都是这种客户端与服务端进行通信的模式。Java中Socket与ServerSocket即对应着网络中的客户端与服务端。
如何构造一个Socket对象:
通常都是用Socket的构造方法来获得常用的是:

Socket socket = new Socket(InetAddress.getByName(host),port);

而ServerSocket对象的构造常用:

ServerSocket ss = new ServerSocket(port);

y因为服务端一般只用接受请求即可,所以只需要端口号即可,如果需要返回数据给客户端,就需要使用Socket类来完成。ServerSocket含有一个accept() 方法,用来返回所连接的那个客户端的Socket对象。
所以Socket,ServerSocket中分别包含着客户端与服务端的位置信息,即IP地址与端口号,接下来就是传输问题。

第二点:传输

z在主流的TCP/IP协议中,传输协议其实有两种分别是TCP(传输控制协议),UDP(用户数据报协议)。这两种方法都各有各的优点适用与不同的场景。

  • TCP协议:是一种稳定可靠的传输协议,需要传输两端进行3次握手,建立稳定的传输通道后才可以进行传输。传输特点是,传输稳定,安全,传输数据量大

  • UDP协议:是一种不可靠的传输协议,每个数据报内都包含着,数据源,目的信息等封装在包内,包的指定大小为64K。发送端和接收端都不知道何时会送达,是否被接受等。但是这种方式在传输小数据时效率很高,也有着自己的适用场景

TCP传输

在TCP传输中,需要对客户端,服务端程序进行编写,以下为编写思路:

  • 客户端:

    1. 创建一个Socket对象,通过构造器指明服务端IP地址以及端口号
    2. 适用流操作getOutStream(),发送数据,方法返回OutputStream的对象
    3. 具体的输出过程
    4. 关闭相应的流操作

以下是示例代码:

public void client(){
        Socket socket = null;
        java.io.OutputStream os = null;
        try {
            socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);

            os = socket.getOutputStream();

            os.write("我是客户端".getBytes());
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(os != null){
                try{
                    os.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
            if(socket != null){
                try {
                    socket.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
  • 服务端:

    1. 创建一个ServerSocket对象,通过构造器指明自身的端口号
    2. 调用其accept()方法,返回Socket对象
    3. 调用Socket对象的getInputStream()方法获取一个从客户端发送过来的输入流
    4. 对获取的输入流进行操作
    5. 关闭相应的流,以及Socket,ServerSocket

以下时示例代码:

public void server(){
        ServerSocket ss = null;
        Socket s = null;
        InputStream is = null;
        try {
            ss = new ServerSocket(9090);
            s = ss.accept();
            is = s.getInputStream();
            byte[] b = new byte[20];
            int len;
            while((len = is.read(b)) != -1){
                String str = new String(b,0,len);
                System.out.println(str);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if(s != null){
                try {
                    s.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }if(ss != null){
                try {
                    ss.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

UDP传输

类DatagramSocket,DatagramPacket 实现了给予UDP的实现。DatagramSocket实现发送于接收操作,DatagramPacket则包含着所有的地址与数据信息。
发送端与接收端的操作流程相似,只不过一个时发送方法,一个是接收方法。
1. 创建一个DatagramSocket对象,一个DatagramPacket对象。
2. 将数据以及IP地址,端口号封装到DatagramPacket对象中
3. 调用Datagrams对象进行发送或接受

以下为示例代码

public void send(){
            DatagramSocket ds = null;
            try {
                ds = new DatagramSocket();
                byte[] b = "我是数据".getBytes();
                DatagramPacket pack = new DatagramPacket(b,0,b.length,InetAddress.getByName("127.0.0.1"),9090);

                ds.send(pack);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                if(ds != null){
                    ds.close();
                }
            }
    }

    public void receive(){
        DatagramSocket ds = null;
        try {
            ds = new DatagramSocket(9090);
            byte[] b = new byte[1024];
            DatagramPacket pack = new DatagramPacket(b,0,b.length);
            ds.receive(pack);

            String str = new String(pack.getData(),0,pack.getLength());
            System.out.println(str);
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(ds != null){
                ds.close();
            }
        }
    }

注:在TCP传输中,如果客户端与服务端有很多信息来回交互的话,由于InputStream方法中的read方法会一直等待输入,即使你自己输入完毕,它依然会等待而导致的阻塞,使得后续的交互无法完成,这个时候就需要使用Socket对象的shutdownOutput()方法告诉服务端已经输出完毕,服务端的输入才会停止接受,开始执行输入以后的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值