您的位置:首页 > 理论基础 > 计算机网络

黑马程序员-网络编程

2015-10-15 11:58 465 查看
——- android培训java培训、期待与您交流! ———-

网络编程

UDP和TCP协议各自优缺点

1)UDP面向无连接,数据报大小有限制64K之内封包,不可靠,容易丢包,但是速度快!因此针对于数据不重要,追求速度快的常用此类协议,如聊天工具/网络视频会议。

2)TCP面向连接,可传输大树据,经过三次握手协议,可靠,但是速度慢,消耗资源。TCP相当于打电话,UDP相当于邮局寄信。下载用的是TCP。

(一)UDP协议

UDP发送数据步骤四步

1)创建socket对象

2)确定数据,并把数据打包

3)发送数据

4)关闭资源socket

[code]public class UDPSend
{
    public static void main(String args[])
    {
        DatagramSocket ds = new DatagramSocket(8888);
        byte[] buf = "hello world!".getBytes();
        DatagramPacket dp = new DatagramPacket(buf,buf.length,"192.163.1.34","10000");
        ds.send(dp);
        ds.close();
    }
}


UDP接受数据步骤

1)创建socket对象,并指定接受端口号

2)定义空的数据报,准备存储接受到的数据,并利用数据报中的方法解析数据的各种信息。

3)接收数据

4)解析数据

5)关闭资源

[code]public class UDPRece
{
    public static void main(String args[])
    {
        DatagramSocket ds = new DatagramSocket(8888);
        byte[] buf = new byte[1024];//最大为6k
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        ds.receive(dp);
        String address = dp.getAdrress().getHostAdrress();
        String data = new String(dp.getData(),0,dp.getLength());
        int port = dp.getPort();
        System.out.println(address+"..."+data+"..."+port);
        ds.close();
    }
}


192.168.1.255是个广播地址。可以给所有机器发广播。

示例1: 从键盘接收数据,可以一对一发,也可以群发。

[code]public class UDPSend
{
    public static void main(String args[])
    {
        DatagramSocket ds = new DatagramSocket(8888);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while((line=br.readLine())!=null)
        {
            if(line.equals("bye"))
                break;
            byte[] buf = line.getBytes();
            DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.163.1.34"),"10000");
            ds.send(dp);
        }
        ds.close();
    }
}


[code]public class UDPRece
{
    public static void main(String args[])
    {
        DatagramSocket ds = new DatagramSocket(8888);
        while(true)
        {
            byte[] buf = new byte[1024];//最大为6k
            DatagramPacket dp = new DatagramPacket(buf,buf.length);
            ds.receive(dp);
            String address = dp.getAdrress().getHostAdrress();
            String data = new String(dp.getData(),0,dp.getLength());
            int port = dp.getPort();
            System.out.println(address+"..."+data+"..."+port);
        }
    }
}


示例2:聊天工具,用两个线程来写,同样是从键盘录入数据。

[code]class UDPSend implements Runnable
{
    private DatagramSocket ds;
    public UDPSend(DatagramSocket ds)
    {
        this.ds = ds;
    }
    public void run()
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while((line=br.readLine())!=null)
        {
            if(line.equals("bye"))
                break;
            byte[] buf = line.getBytes();
            DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.163.1.34"),"10000");
            ds.send(dp);
        }
        ds.close();
    }
}


[code]class UDPRece implements Runnable
{
    private DatagramSocket ds;
    public UDPRece(DatagramSocket ds)
    {
        this.ds = ds;
    }
    public void run()
    {
        while(true)
        {
            byte[] buf = new byte[1024];//最大为6k
            DatagramPacket dp = new DatagramPacket(buf,buf.length);
            ds.receive(dp);
            String address = dp.getAdrress().getHostAdrress();
            String data = new String(dp.getData(),0,dp.getLength());
            int port = dp.getPort();
            System.out.println(address+"..."+data+"..."+port);
        }
    }
}


[code]public class TestDemo
{
    public static void main(String args[])
    {
        DatagramSocket ds1 = new DatagramSocket();
        DatagramSocket ds2 = new DatagramSocket(10000);
        new Thread(new UDPSend(ds1));
        new Thread(new UDPRece(ds2));
    }
}


(二)TCP协议

注1:客户端和服务器

注2:需要建立连接才能执行,需要先运行服务器,在运行客户端

客户端建立步骤

1. 创建socket对象,并设置连接地址和端口号

2. 获得输出流

3. 加载数据到输出流中

4. 关闭客户端

[code]class TCPClient
{
    public static void main(String args[])
    {
        Socket sc = new Socket("192.168.1.254",10003);
        OutputStream out = ss.getOutputStream();
        out.write("hello world".getBytes());
        sc.close();
    }
}


服务器建立步骤

1. 创建server对象,设置自己的监听端口号

2. 获得客户端socket对象

3. 获得客户端对象的输入流,并读取数据

4. 关闭客户端。

[code]class TCPServer
{
    public static void main(String args[])
    {
        ServerSocket ss = new ServerSocket(10003);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        System.out.println(ip+".......");
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf,0,len));
        s.close();
    }
}


示例3:客户端发送数据,服务器端接收数据,并反馈给客户端,客户端接收反馈并打印。

[code]class TCPClient
{
    public static void main(String args[])
    {
        Socket s = new Socket("192.168.1.254",10001);
        OutputStream out = s.getOutputStream();
        out.write("你好,服务器!".getBytes());

        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=in.read(buf))!=-1)
        {
            System.out.println(new String(buf,0,len));
        }
        s.close();
    }
}


[code]class TCPServer
{
    public static void main(String args[])
    {
        ServerSocket ss = new ServerSocket(10001);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        InputStream in = s.getInputStream();
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        System.out.println(new String(buf,0,len));

        OutputStream out = s.getOutputStream();
        out.write("客户端,谢谢,已收到!!".getBytes());
        s.close();
        ss.close();
    }
}


示例4:客户端通过键盘录入文本数据,服务器将文本转换成大写返回给客户端。

1)用字符缓冲流完成

2)改错。客户端和服务器都在莫名的等待,原因是里面出现了阻塞式方法,这些方法没有读到结束标记,所以一直处于等待状态。

[code]class TCPClient
{
    public static void main(String args[])
    {
        Socket s = new Socket("192.168.1.254",10002);
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufbw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        BufferedReader bufbr = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;
        while((line=in.readLine())!=null)
        {
            if(line.equals("over"))
                break;
            bufbw.write(line);
            bufbw.newLine();
            bufbw.flush();

            String str = bufr.readLine();
            System.out.println("server:"+str);
        }
    }
}


[code]class TCPServer
{
    public static void main(String args[])
    {
        ServerSocket ss = new ServerSocket(10003);
        Socket s = ss.accept();
        BufferedReader bufbr = new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bufbw = new BufferedReader(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while((line = bufbr.readLine())!=null)
        {
            bufbw.write(line.toUpperCase());
            bufbw.newLine();
            bufbw.flush();
        }
        s.close();
        ss.close();
    }
}


示例5:上传文本数据。从客户传送硬盘文件到服务器端硬盘。文本文件。

出现问题:

1)没有结束标记位

2)socket内部定义的结束关闭流标志位的方法。shutdownOutput();

[code]class TCPClient
{
    public static void main(String args[])
    {
        Socket s = new Socket("192.168.1.254",10002);
        BufferedReader in = new BufferedReader(new FileReader("c:\\client.txt"));
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()),true);
         bufbr = new BufferedReader(new InputStreamReader(s.getInputStream()));

        String line = null;
        while((line=in.readLine())!=null)
        {
            pw.println(line);
        }
        s.shutdownOutput();
        String str = bufr.readLine();
        System.out.println("server:"+str);
        in.close();
        s.close();
    }
}


[code]class TCPServer
{
    public static void main(String args[])
    {
        ServerSocket ss = new ServerSocket(10003);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        BufferedReader bufbr = new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\server.txt"),true);
        String line = null;
        while((line = bufbr.readLine())!=null)
        {
            bw.write(line);
        }

        PrintWriter bufbw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
        bufbw.write("上传成功!!!!")

        s.close();
        ss.close();
    }
}


示例6:上传图片。(练习)

一个传一个收。

[code]class TCPClient
{
    public static void main(String args[])
    {
        Socket s = new Socket("192.168.1.254",10002);
        InputStream in = new FileInputStream("c:\\1.png");
        OutputStream out = s.getOutputStream();
        byte[] buf = new byte[1024];
        int len = 0 ; 
        while((len=in.read(buf))!=-1)
        {
            out.write(buf);
        }
        s.shutdownOutput();
        InputStream is = s.getInputStream();
        byte[] buf1 = new byte[1024];
        int len1 = is.read(buf1);
        System.out.println(new String(buf1,0,len1));
        in.close();
        s.close();
    }
}


[code]class TCPServer
{
    public static void main(String args[])
    {
        ServerSocket ss = new ServerSocket(10003);
        Socket s = ss.accept();
        String ip = s.getInetAddress().getHostAddress();
        InputStream in = s.getInputStream();
        OutputStream ou = new FileOutputStream("d:\\2.png");
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=in.read(buf))!=-1)
            ou.write(buf,0,len);
        OutputStream out = s.getOutputStream();
        out.write("上传成功!!".getBytes());
        ou.close();
        s.close();
        ss.close();
    }
}


一个服务器,同时可以处理多个客户端的请求。用多线程处理。

注意:需要开启新的线程,需要保存路径是原有文件不被覆盖,需要传输特定格式和特定大小的文件。

[code]class uploadThread
{
    private Socket socket;
    public uploadThread(Socket socket)
    {
        this.socket = socket;
    }
    public void run()
    {
        try
        {
            int count = 1;
            String ip = s.getInetAddress().getHostAddress();
            InputStream in = s.getInputStream();
            File file = new File(ip+"("+count+")"+".png");
            while(file.exist())
            {
                File file = new File(ip+"("+(count++)+")"+".png");
            }
            OutputStream ou = new FileOutputStream(file);
            byte[] buf = new byte[1024];
            int len = 0;
            while((len=in.read(buf))!=-1)
                ou.write(buf,0,len);
            OutputStream out = s.getOutputStream();
            out.write("上传成功!!".getBytes());
            ou.close();
            s.close();
        }catch(Exception e)
        {
            throw new RuntimeException(ip+"上传失败!!")
        }
    }
}


[code]class TCPServer
{
    public static void main(String args[])
    {
        ServerSocket ss = new ServerSocket(10003);
        while(true)
        {
            Socket s = ss.accept();
            new Thread(new uploadThread(s)).start();
        }
    }
}


[code]class TCPClient
{
    public static void main(String args[])
    {
        if(args.length!=1)
        {
            System.out.println("请选择一个图片格式的文件上传");
            return;
        }
        File file = args[0];
        if(!(file.exist()&&file.isFile()))
        {
            System.out.println("该文件有问题,要么不存在,要么不是文件格式");
            return;
        }
        if(file.getName().endsWith(".jpg"))
        {
            System.out.println("该图片格式不正确,请重新选择");
            return;
        }
        if(file.length()>1024*1024*5)
        {
            System.out.println("文件过大,请重新选择");
            return;
        }
        Socket s = new Socket("192.168.1.254",10002);
        InputStream in = new FileInputStream(file);
        OutputStream out = s.getOutputStream();
        byte[] buf = new byte[1024];
        int len = 0 ; 
        while((len=in.read(buf))!=-1)
        {
            out.write(buf);
        }
        s.shutdownOutput();
        InputStream is = s.getInputStream();
        byte[] buf1 = new byte[1024];
        int len1 = is.read(buf1);
        System.out.println(new String(buf1,0,len1));
        in.close();
        s.close();
    }
}


(三) URL

我们所常用的浏览器,实际上就是一个客户端,输入内容为http://IP:端口号?key=alue,就相当于发送请求。

我们把http协议,IP地址,端口号和请求内容封装到一个类中,称为URL。

通过URL,我们可以:

(1)获得协议名称,IP地址,端口号,请求内容等;

(2)可以直接获得客户端和服务器端的连接通道。

[code]public class URLDemo
{
    public static void main(String args[]) throws Exception
    {
        URL url = new URL("http://192.168.1.245:8080/myweb/demo.html?name=hahha&age=39");

        System.out.println("getProtocol()"+url.getProtocol());//获得协议
        System.out.println("getHost()"+url.getHost());//获得IP地址
        System.out.println("getPort()"+url.getPort());//获得端口号
        System.out.println("getPath()"+url.getPath());//获得路径
        System.out.println("getFile()"+url.getFile());//获得查找内容
        System.out.println("getQuery()"+url.getQuery());//获得查找内容

        URLConnection con = url.getConnection();//返回数据没有头信息。//这属于应用层。
        InputStream in = url.openStream();//直接开流
    }
}


需要注意一点:getPort()方法,如果没有输入端口号,则默认为-1;需要如下判断:

[code]int port = url.getPort();
        if(port==-1)
            port = 80;


以上是网络编程的基本概念和基本思想,多做练习,多理解,多复习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: