Java简单的网络编程

时间有些紧迫了,一个星期的悠闲时光也就这么结束了,开始巩固新东西,今天来说一说Java中的网络编程

学习网络编程首先需要知道一些计算机网络的基本知识

TCP/IP

这里写图片描述

ip地址划分

这里写图片描述

注意: A类地址中的127开头的地址都是保留地址,例如最常见的127.0.0.1代表localhost,C类地址中的私有地址:192.168.X.X表明不是公网地址。

端口

这里写图片描述

URL

这里写图片描述

TCP三次握手

这里写图片描述

TCP四次挥手

这里写图片描述

InetAddress类

InetAddress类有两个子类Inet4Address、Inet6Address,分别表示IPv4和IPv6。InetAddress没有提供构造方法,但可以通过类中的静态方法来获取InetAddress类的实例。

例子

package homework;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner;

public class InetAddressDemo {
    public static void main(String []args){
        Scanner sc=new Scanner(System.in);
        System.out.println("input the domain:");
        String dnsname=sc.next();
        InetAddress local =null;
        try{
            local =InetAddress.getByName(dnsname);
            System.out.println("dsnmain IP:"+local.getHostAddress());
            System.out.println("domainName:"+local.getHostName());
            local=InetAddress.getLocalHost();
            System.out.println("host ip:"+local.getHostAddress());
            System.out.println("host name:"+local.getHostName());
        }catch (UnknownHostException e){
            e.printStackTrace();
        }

    }
}

这里写图片描述

URL类

这里写图片描述

例子

package homework;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Scanner;

public class UrlDemo {
    public static void main(String []args){
        System.out.println("input the URL:");
        Scanner sc=new Scanner(System.in);
        String urlstr=sc.next();
        URL url=null;
        try{
            url=new URL(urlstr);
            System.out.println("host:"+url.getHost());
            System.out.println("path:"+url.getPath());
            System.out.println("port:"+url.getPort());
            System.out.println("protocol:"+url.getProtocol());
            System.out.println("information:"+url.getUserInfo());
            System.out.println("content:"+url.getQuery());
        }catch (Exception e){
            e.printStackTrace();
        }
        try{
            InputStream in=url.openStream();
            BufferedReader bin=new BufferedReader(new InputStreamReader(in));
            String strline=null;
            while ((strline=bin.readLine())!=null)
                System.out.println(strline);
            bin.close();
        }catch (Exception e){
            e.printStackTrace();
        }


    }
}

这里写图片描述

URLConnection类

URLConnection类的对象可以与指定的URL建立动态的连接,同时使用URLConnection类的对象可以实现向服务器发送请求,将数据送回服务器并检查远程资源的一些属性。 一般创建URLConnection类对象使用的是URL的openConnection()方法,URLConnection类的常用方法如下:

这里写图片描述

下载文件代码

package homework;
import java.text.DateFormat;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class URLConDemo {
    public static void main(String []args){

        URLConnection urlCon=null;
        try{
            URL url=new URL("http://baobab.kaiyanapp.com/api/v1/playUrl?vid=63613&editionType=default&source=aliyun");
            urlCon =url.openConnection();
        }catch (Exception e){
            e.printStackTrace();
        }

        DateFormat d=DateFormat.getDateTimeInstance();
        long t1=System.currentTimeMillis();
        System.out.println("start time: "+d.format(t1));

        long length=urlCon.getContentLength()/1024;
        System.out.println("the filelen: "+length+"KB");
        System.out.println("filetype: "+urlCon.getContentType());

        try{
            InputStream in=urlCon.getInputStream();
            BufferedInputStream bin=new BufferedInputStream(in);
            FileOutputStream fout=new FileOutputStream("one.mp4");
            int len=0;
            float sum=0;
            byte b[]=new byte[1024*1024];
            System.out.println("==Start Download==");
            while((len=bin.read(b,0,1024*1024))!=-1){
                fout.write(b,0,len);
                sum+=len/1024;
                System.out.print("\rhave down: "+sum/length*100+"%");
            }
            System.out.println();

            fout.close();
            bin.close();
            in.close();

            long t2=System.currentTimeMillis();
            System.out.println("End time: "+d.format(t2));
            System.out.println("the go through time:"+(t2-t1)+"ms");
            System.out.println("the speed: "+(float)length*1000/1024/(t2-t1)+"MB/s");
            System.out.println("==End Download==");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

这里写图片描述

附赠几个MP4下载链接

http://baobab.kaiyanapp.com/api/v1/playUrl?vid=11111&editionType=default&source=aliyun

http://baobab.kaiyanapp.com/api/v1/playUrl?vid=23456&editionType=default&source=aliyun

http://baobab.kaiyanapp.com/api/v1/playUrl?vid=63613&editionType=default&source=aliyun

http://baobab.kaiyanapp.com/api/v1/playUrl?vid=54321&editionType=default&source=aliyun

TCP通信

进行TCP网络通信需要使用两个类,一个是服务器套接字ServerSocket类,一个是客户端套接字Socket类,服务器套接字一次只能与一个客户端套接字连接,若多态客户端同时请求连接则可以采用多线程,服务器会将请求连接的客户端放入对列中,然后从中取出一个套接字与服务器的套接字相连,最大容纳数默认为50.

ServerSocket类

当ServerSocket类对象创建后,调用accept()方法接收来自客户端发来的连接请求,accept()方法采用的是“阻塞方式监听,直到客户端连接成功后程序才会向下继续执行并返回一个与客户端Socket对象相连的Socket对象。

  • 服务器端的Socket对象使用getOutputStream()方法获取的输出流将指向客户端Socket对象使用getInputStream()方法获取的那个输入流;

  • 同样的服务器端的Socket对象使用的getInputStream()方法获取的输入流将指向客户端Socket对象使用getOutputSream()方法获取的输出流。

Socket类

在Java中,有专门的Socket类来处理用户的请求和响应,利用Socket类的方法,就可以实现两台计算机之间的通信。
客户端创建Socket对象之后,会向指定的IP地址即端口尝试连接,服务器端的Socket接到连接请求后创建新的Socket与客户端的Socket进行连接。
若服务器的Socket与客户端的Socket连接成功后,就可以获取Socket中的输入流与输出流进行通信了。
PS:在Socket类的诸多方法中,最常见的getInputStream和getOutputStream是一定要使用的方法。

这里写图片描述

一对一通信实例

服务器端

package homework;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.DateFormat;
public class MyserverDemo {
    public static void main(String []args){
        ServerSocket server=null;
        Socket socket=null;
        DataInputStream din=null;
        DataOutputStream dout=null;
        DateFormat dd=DateFormat.getDateTimeInstance();
        try{
            server =new ServerSocket(8000);
            System.out.println(dd.format(System.currentTimeMillis())+"\twait the client.....");
            socket =server.accept();
            System.out.println(dd.format(System.currentTimeMillis())+"\tclient have connect....\nclient from\t"+socket.getInetAddress().getHostAddress());
            din=new DataInputStream(socket.getInputStream());
            dout=new DataOutputStream(socket.getOutputStream());
            String strMessage=null;
            Scanner sc=new Scanner(System.in);
            boolean flag=true;
            while(flag){
                strMessage=din.readUTF();
                if(!strMessage.equals("bye")){
                    System.out.println(dd.format(System.currentTimeMillis())+"\tclient message:\n"+strMessage);
                    System.out.println(dd.format(System.currentTimeMillis())+"\treply: ");
                    strMessage=sc.next();
                    dout.writeUTF(strMessage);
                    dout.flush();
                }else {
                    din.close();
                    dout.close();
                    flag=false;
                }
            }
            server.close();
            System.out.println(dd.format(System.currentTimeMillis())+"\tserver exit()...");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

这里写图片描述

客户机端

package homework;
import java.io.*;
import java.net.*;
import java.text.DateFormat;
import java.util.*;
public class MyclientDemo {
    public static void main(String []args){
        Socket socket=null;
        DataInputStream din=null;
        DataOutputStream dout=null;
        DateFormat df=DateFormat.getDateTimeInstance();
        try{
            System.out.println(df.format(System.currentTimeMillis())+"\ttry connect server.....");
            socket =new Socket("127.0.0.1",8000);
            System.out.println(df.format(System.currentTimeMillis())+"\tconnect successful");
            din=new DataInputStream(socket.getInputStream());
            dout=new DataOutputStream(socket.getOutputStream());
            String strMassage=null;
            Scanner sc=new Scanner(System.in);
            boolean flag=true;
            while (flag){
                System.out.println(df.format(System.currentTimeMillis())+"\tsent message:");
                strMassage =sc.next();
                dout.writeUTF(strMassage);
                dout.flush();
                strMassage=din.readUTF();
                if(!strMassage.equals("bye")){
                    System.out.println(df.format(System.currentTimeMillis())+"\treceive message:\n"+strMassage);
                }else {
                    din.close();
                    dout.close();
                    flag=false;
                }
            }
            socket.close();
            System.out.println(df.format(System.currentTimeMillis())+"\tserver exit()...");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

这里写图片描述

修改服务器端,实现一对多

客户端就是前面的示例无需任何修改,只需修改服务器端的示例如下即可
(方法就是简单的多线程实现方法,即实现Runnable抽象类)

package homework;

import java.io.*;
import java.net.*;
import java.util.*;
public class MyServerDemo2 {
    public static void main(String []arg){
        ServerSocket server=null;
        Socket socket=null;
        try{
            server =new ServerSocket(8000);
            System.out.println("wait client.....");
            while(true){
                socket=server.accept();
                new Thread(new ServerThread(socket)).start();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
class ServerThread implements Runnable{
    private Socket socket;
    public ServerThread(Socket socket){
        this.socket=socket;
    }
    public void run(){
        DataInputStream din=null;
        DataOutputStream dout=null;
        try{
            System.out.println("client connect....\nclient from\t"+socket.getInetAddress().getHostAddress());
            din=new DataInputStream(socket.getInputStream());
            dout=new DataOutputStream(socket.getOutputStream());
            String strMassage=null;
            Scanner sc=new Scanner(System.in);
            boolean flag=true;
            while(flag){
                strMassage=din.readUTF();
                if(!strMassage.equals("bye")){
                    System.out.println("client message:\n"+strMassage);
                    System.out.println("reply client:");
                    strMassage=sc.next();
                    dout.writeUTF(strMassage);
                    dout.flush();
                }else {
                    din.close();
                    dout.close();
                    flag=false;
                }
            }
            socket.close();
            System.out.println("server exit()");

        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

这里写图片描述

UDP

在Java中一般使用DatagramPacket和DatagramSocket类实现UDP通信。

DatagramSocket类用于创建接受或发送数据包的Socket对象,在C/S程序中使用UDP协议时,实际上并没有明显的服务器端和客户端的区别,因为通信双方都需要先建立一个DatagramSocket对象,用来接收或发送数据报,然后使用DatagramPacket对象作为传输数据的载体。

简单示例

  • UDP客户端
package homework;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPClientDemo {
    public static void main(String []args){
        DatagramSocket dsocket=null;
        DatagramPacket dPack=null;
        byte b[]=new byte[512];
        try{
            dsocket =new DatagramSocket(8000);
            dPack=new DatagramPacket(b,512);
            System.out.println("wait digital....");
            while(true){
                dsocket.receive(dPack);
                String message=new String(dPack.getData(),0,dPack.getLength());
                System.out.println("remote ip: "+dPack.getAddress().getHostAddress());
                System.out.println("remote port: "+dPack.getPort());
                System.out.println("receive message:"+message);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
  • UDP服务器端
package homework;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class UDPServerDemo {
    public static void main(String []args){
        DatagramSocket dSock=null;
        DatagramPacket dpack=null;
        Scanner sc=new Scanner(System.in);
        try{
            InetAddress local=InetAddress.getLocalHost();
            dSock=new DatagramSocket(8001);
            String mssage=null;
            while(true){
                System.out.println("sent message");
                mssage=sc.next();
                dpack=new DatagramPacket(mssage.getBytes(),mssage.length(),local,8000);
                dSock.send(dpack);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

首先开启客户端,然后开启服务器端发送数据

这里写图片描述

这里写图片描述

注意: 上述TCP的ServerSocket只是监听8000端口,绑定端口的只有客户端的Socket,即服务器端的Socket并没有绑定端口。而UDP的DatagramSocket的客户端和服务器端口都会绑定,但绑定是具有唯一性的,所以UDP客户端和服务器绑定的端口是不一样的,也就是上面的客户端绑定端口8000,服务器绑定端口8001。

小结

Java网络编程就是舒服,比起C/C++需要自己来实现协议来说,Java只需要熟悉如何进行操作就行了,在一方面Java比之C/C++又更胜一筹了,不过原理还是或多或少的需要去钻研一下的,毕竟需要知道自己面对的是什么才对。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值