黑马程序员04_网络编程

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

TCP/IP参考模型

应用层、传输层、网络层、链路层


UDP总结:

1、将数据源和目的地封装到数据包中,不需要建立连接

2、每个数据包的大小限制在64k以内

3、因无连接。是不可靠协议

4、不需要建立连接。速度快

UDP发送端:

    package com.xiaozhi.udp;  
      
    import java.net.DatagramPacket;  
    import java.net.DatagramSocket;  
    import java.net.InetAddress;  
      
    public class SendClient {  
      
        public static void main(String[] args) throws Exception {  
      
            //通过DatagramSocket建立udp服务  
            DatagramSocket datagramSocket=new DatagramSocket();  
              
            //确定数据并封装成数据包  
            byte[]bs="黑马我来了".getBytes();  
            DatagramPacket datagramPacket=new DatagramPacket(bs, bs.length,InetAddress.getByName("121.251.158.251"),10000);  
              
            //发送数据  
            datagramSocket.send(datagramPacket);  
              
            //关闭资源  
            datagramSocket.close();  
        }  
    }  
UDP接受端:

    package com.xiaozhi.udp;  
      
    import java.net.DatagramPacket;  
    import java.net.DatagramSocket;  
      
    public class ReviewClient {  
      
        public static void main(String[] args) throws Exception {  
      
            //通过DatagramSocket建立udp服务,可以指定端口号,也可以不指定  
            DatagramSocket datagramSocket=new DatagramSocket(10000);  
              
            //定义数据包,用于存储数据  
            byte[]bs=new byte[1024];  
            DatagramPacket datagramPacket=new DatagramPacket(bs, bs.length);  
              
            //接受数据,receive是阻塞式方法  
            while(true){  
                datagramSocket.receive(datagramPacket);  
                System.out.println(new String(datagramPacket.getData()));  
            }  
    //          datagramSocket.close();  
              
        }  
      
    }  

TCP的总结:

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

2、在连接中进行大量数据的传输

3、通过三次握手完成连接、是可靠协议

4、必须建立连接。效率稍低



使用TCP协议写一个可以上传文件的服务器和客户端


客户端步骤:
1、首先创建客户端的Socket服务,指定目的主机和端口号

2、得到上传文件的输入流

3、得到Socket的输出流

4、关闭流、关闭Socket

服务端步骤:

1、创建服务器端的ServerSocket服务,并指定端口号

2、通过accept接受客户端Socket对象

3、通过多线程技术,将每一个接受到的客户端Socket对象封装进一个线程中。

4、在run方法中得到保存文件的输出流、Socket的输入流

5、关闭流、关闭Socket

TCP上传客户端代码:

    package com.xiaozhi.jingtian.tcp;    
      
    import java.io.FileInputStream;    
    import java.io.IOException;    
    import java.io.OutputStream;    
    import java.net.Socket;    
      
    public class UploadClient {    
      
        public static void main(String[] args) throws Exception, IOException {    
            //创建客户端的Socket服务,指定目的主机和端口号    
            Socket socket=new Socket("121.251.158.251",10000);    
                
            FileInputStream fileInputStream=new FileInputStream("c://1.bmp");    
            OutputStream outputStream=socket.getOutputStream();    
                
            byte[]buffer=new byte[1024];    
            int lang = 0;    
            while((lang=fileInputStream.read(buffer))!=-1){    
                outputStream.write(buffer, 0, lang);    
            }    
              
            fileInputStream.close();    
            outputStream.close();    
            socket.close();    
        }    
    }    

TCP上传服务器端代码:
    package com.xiaozhi.jingtian.tcp;  
      
    import java.io.FileNotFoundException;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.InputStream;  
    import java.net.ServerSocket;  
    import java.net.Socket;  
      
    import javax.xml.crypto.Data;  
      
    public class UploadServer {  
      
        public static void main(String[] args) throws Exception {  
            //创建服务端的Socket服务,指定端口号  
            ServerSocket serverSocket=new ServerSocket(10000);  
              
            while(true){  
                //通过accept方法获取连接过来的Socket对象  
                Socket socket=serverSocket.accept();  
                new MyThread(socket).start();  
            }  
              
        }  
    }  
      
    class MyThread extends Thread{  
        private Socket socket;  
          
        public MyThread(Socket socket) {  
            this.socket = socket;  
        }  
      
        @Override  
        public void run() {  
            try {  
                System.out.println(socket.getInetAddress().getHostAddress()+"上传文件");  
                FileOutputStream fileOutputStream=new FileOutputStream("c://"+System.currentTimeMillis()+".bmp");  
                InputStream inputStream=socket.getInputStream();  
                  
                byte[]buffer=new byte[1024];  
                int lang = 0;  
                while((lang=inputStream.read(buffer))!=-1){  
                    fileOutputStream.write(buffer, 0, lang);  
                }  
                  
                fileOutputStream.close();  
                inputStream.close();  
                socket.close();  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  


另外需要注意:

如果上传的文件是文本文件,可以使用缓冲流来上传,提高效率。

但是是BufferedReader的readLIne()方法判断的是每行是否有换行符。所以客户端发送数据的时候需要加换行。

也可以使用PrintWriter,PrintWriter更方便一下,既可以设置autoFlush 的参数为true,自动刷新。又可以使用println方法,自带换行符,甚是方便。

下面是使用缓冲流优化的客户端,服务器端代码:

    package com.xiaozhi.jingtian.tcp;  
      
    import java.io.BufferedReader;  
    import java.io.BufferedWriter;  
    import java.io.FileInputStream;  
    import java.io.IOException;  
    import java.io.InputStreamReader;  
    import java.io.OutputStreamWriter;  
    import java.net.Socket;  
      
    public class UploadClient {  
      
        public static void main(String[] args) throws Exception, IOException {  
            //创建客户端的Socket服务,指定目的主机和端口号  
            Socket socket=new Socket("121.251.158.251",10000);  
              
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream("c://1.txt")));   
            BufferedWriter bufferedWriter= new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));  
              
            String line=null;  
            while((line=bufferedReader.readLine())!=null){  
                bufferedWriter.write(line);  
                bufferedWriter.newLine();  
                bufferedWriter.flush();  
            }  
          
            bufferedReader.close();  
            bufferedWriter.close();  
            socket.close();  
        }  
    }  
    package com.xiaozhi.jingtian.tcp;  
      
    import java.io.BufferedReader;  
    import java.io.BufferedWriter;  
    import java.io.FileNotFoundException;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.InputStream;  
    import java.io.InputStreamReader;  
    import java.io.OutputStreamWriter;  
    import java.net.ServerSocket;  
    import java.net.Socket;  
      
    import javax.xml.crypto.Data;  
      
    public class UploadServer {  
      
        public static void main(String[] args) throws Exception {  
            //创建服务端的Socket服务,指定端口号  
            ServerSocket serverSocket=new ServerSocket(10000);  
              
            while(true){  
                //通过accept方法获取连接过来的Socket对象  
                Socket socket=serverSocket.accept();  
                new MyThread(socket).start();  
            }  
              
        }  
    }  
      
    class MyThread extends Thread{  
        private Socket socket;  
          
        public MyThread(Socket socket) {  
            this.socket = socket;  
        }  
      
        @Override  
        public void run() {  
            try {  
                System.out.println(socket.getInetAddress().getHostAddress()+"上传文件");  
                BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));  
                BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c://"+System.currentTimeMillis()+".txt")));  
                  
                String line=null;  
                while((line=bufferedReader.readLine())!=null){  
                    bufferedWriter.write(line);  
                    bufferedWriter.newLine();  
                    bufferedWriter.flush();  
                }  
                  
                bufferedReader.close();  
                bufferedWriter.close();  
                socket.close();  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

下面是使用PrintWriter优化的客户端、服务端代码
    package com.xiaozhi.jingtian.tcp;  
      
    import java.io.BufferedReader;  
    import java.io.BufferedWriter;  
    import java.io.FileInputStream;  
    import java.io.IOException;  
    import java.io.InputStreamReader;  
    import java.io.OutputStreamWriter;  
    import java.io.PrintWriter;  
    import java.net.Socket;  
      
    public class UploadClient {  
      
        public static void main(String[] args) throws Exception, IOException {  
            //创建客户端的Socket服务,指定目的主机和端口号  
            Socket socket=new Socket("121.251.158.251",10000);  
              
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream("c://1.txt")));   
            PrintWriter printWriter =new PrintWriter(socket.getOutputStream(),true);  
              
            String line=null;  
            while((line=bufferedReader.readLine())!=null){  
                printWriter.println(line);  
            }  
            bufferedReader.close();  
            printWriter.close();  
            socket.close();  
        }  
    }  

    package com.xiaozhi.jingtian.tcp;  
      
    import java.io.BufferedReader;  
    import java.io.BufferedWriter;  
    import java.io.FileNotFoundException;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  
    import java.io.InputStream;  
    import java.io.InputStreamReader;  
    import java.io.OutputStreamWriter;  
    import java.io.PrintWriter;  
    import java.net.ServerSocket;  
    import java.net.Socket;  
      
    import javax.xml.crypto.Data;  
      
    public class UploadServer {  
      
        public static void main(String[] args) throws Exception {  
            //创建服务端的Socket服务,指定端口号  
            ServerSocket serverSocket=new ServerSocket(10000);  
              
            while(true){  
                //通过accept方法获取连接过来的Socket对象  
                Socket socket=serverSocket.accept();  
                new MyThread(socket).start();  
            }  
              
        }  
    }  
      
    class MyThread extends Thread{  
        private Socket socket;  
          
        public MyThread(Socket socket) {  
            this.socket = socket;  
        }  
      
        @Override  
        public void run() {  
            try {  
                System.out.println(socket.getInetAddress().getHostAddress()+"上传文件");  
                BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));  
                PrintWriter printWriter =new PrintWriter(new FileOutputStream("c://"+System.currentTimeMillis()+".txt"),true);  
                  
                String line=null;  
                while((line=bufferedReader.readLine())!=null){  
                    printWriter.println(line);  
                }  
                  
                bufferedReader.close();  
                printWriter.close();  
                socket.close();  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  


shutdownOutput方法的作用:

关闭客户端的输出流。相当于给流中加入一个结束标记-1。

也可以这样理解s.shutdownOutput();关闭的是客户端的输出流,同时服务器端的输入流也随之关闭。

s.shutdownIntput();也是同样的道理,关闭客户端的输入流,同时服务器端的输出流也随之关闭。




---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值