• 网络编程——第一部分


     

    新博客地址:Temi

    第一讲,第二讲:Java基础第23天-01-网络编程(概述),第23天-02-网络编程(概述2)

    一,网络通信步骤:

      1. 找到对方(通过IP)。
      2. 数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。====端口(逻辑端口)====
      3. 定义通信规则,这个规则成为协议。国际标准化组织定义了TCP/IP协议。======有效端口:0 ~65535,系统使用或保留的端口是:0~ 1024。======

    第三讲:(网络模型)

     

    一,各个层次的协议   (通常用户操作的是应用层,而编程人员需要做的是传输层和网际层)

      1. 网际层:IP协议。
      2. 传输层:TCP/UDP协议。
      3. 应用层:HTTP/FTP 协议。(web开发)。

    二,网络通讯要素:

    1. IP地址:
      1. 网络中设备的标识。
      2. 不易记忆,可用主机名。
      3. 本地回环地址。127.0.0.1  。主机名:localhost
    2. 端口号:
      1. 用于表示进程的逻辑地址。不同进程的标识。
      2. 有效端口:0-65535,其中1-1024系统使用或保留端口。

    三,涉及到的类:

      1. public class InetAddress extends Object implements Serializable       此类表示互联网协议 (IP) 地址。   ====注:此类没有构造方法=====
      2. 方法:public static InetAddress  getByName (String host)  throws UnknownHostException   在给定主机名的情况下确定主机的 IP 地址。
      3. 方法:public static InetAddress[] getAllByName(String host) throws UnknownHostException      在给定主机名的情况下,根据系统上配置的名称服务返回其 IP 地址所组成的数组。
      4. 方法:public static InetAddress getByAddress(byte[] addr) throws UnknownHostException      在给定原始 IP 地址的情况下,返回 InetAddress 对象。
      5. 方法:public String getHostName()    获取此 IP 地址的主机名。
      6. 方法:public String getHostAddress()  返回 IP 地址字符串(以文本表现形式)。

    四,代码练习:

     1 import java.net.*;
     2 
     3 public class IPDemo {
     4              public static void main(String[] args) throws UnknownHostException {
     5                              //声明地址类,表示本地主机
     6                              InetAddress i = InetAddress.getLocalHost();
     7                              
     8                              //输出本地主机的IP地址
     9                              System.out.println(i.getHostAddress());
    10                              
    11                              //已主机名的方式找到主机
    12                              InetAddress my = InetAddress.getByName("Lenovo-PC");
    13                              
    14                              //输出主机地址
    15                              System.out.println(my.getHostAddress());
    16                              
    17                              
    18                              //获取百度所有主机
    19                              InetAddress[] ia = InetAddress.getAllByName("www.baidu.com");
    20                              
    21                              //输出百度主机地址
    22                              for(InetAddress inet : ia){
    23                                  
    24                                  System.out.println(inet.getHostName()+"::"+inet.getHostAddress());
    25                              }
    26                               
    27             }
    28 }

    第四讲:网络编程(IP地址)

    第五讲:网络编程(TCP和UDP)

    一,TCP 和 UDP 简介:

    1. UDP(面向无连接,明确了对方的端口,无论在不在网上,只管传输,不在就会丢失数据。只求速度,应用于网络视频会议和聊天等应用程序中。)
      1. 将数据及源和目的封装在数据包中,不需要建立连接。
      2. 每个数据包的大小限制在64k内。
      3. 因为无连接,是不可靠协议。
      4. 不需要建立连接,所以速度快。
    2. TCP( 是面向连接的,必须连接成功才能传输数据,应用于下载等程序上)
      1. 建立连接形成传输数据的通道。
      2. 可在连接中进行大数据量传输。
      3. 通过三次握手完成数据连接,是可靠协议。===注:三次握手:第一次本方发送请求,第二次对方确认连接,第三次本方再次确认连接成功。====
      4. 必须建立连接,效率稍低。

    第六讲,第七讲:网络编程(Socket),网络编程(Udp-发送端)

    一,Socket 简介:

      1. Socket 是为网络服务提供的一种机制。
      2. 通信的两段都有Socket。
      3. 网络通信其实就是Socket之间的通信。
      4. 数据在两个Socket之间通过IO传输。

    二,DatagramSocket 类简介:

      1. public class DatagramSocketextends Object   此类表示用来发送和接收数据报包的套接字。   ===注:在 DatagramSocket 上总是启用 UDP 广播发送。====
      2. 构造方法:public DatagramSocket() throws SocketException   构造数据报套接字并将其绑定到本地主机上任何可用的端口。
      3. 构造方法:public DatagramSocket(int port) throws SocketException   创建数据报套接字并将其绑定到本地主机上的指定端口。
      4. 方法:public InetAddress getInetAddress()       返回此套接字连接的地址。如果套接字未连接,则返回 null。
      5. 方法:public int getPort()     返回此套接字的端口。如果套接字未连接,则返回 -1。
      6. public void send (DatagramPacket p) throws IOException 从此套接字发送数据报包。

    三,DatagramPacket 类简介(DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。):

      1. public final class DatagramPacketextends Object           此类表示数据报包。
      2. 构造方法:public DatagramPacket(byte[] buf, int offset, int length, InetAddress address,int port)  构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。
      3. 方法:public InetAddress getAddress()  返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
      4. 方法:public int getPort()                    返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。
      5. 方法:public byte[] getData()             返回数据缓冲区。接收到的或将要发送的数据从缓冲区中的偏移量 offset 处开始,持续 length 长度。
      6. 方法:public int getOffset()                返回将要发送或接收到的数据的偏移量。
      7. 方法:public int getLength()               返回将要发送或接收到的数据的长度。

    四,代码练习:

     1 import java.net.*;
     2 
     3 public class UdpSend {
     4              public static void main(String[] args) throws Exception {
     5                  
     6                              //创建Udp服务
     7                            DatagramSocket ds = new DatagramSocket();
     8                            
     9                            //获得发送数据
    10                            byte[] b = "这是发送信息".getBytes();
    11                            
    12                            //构造数据包
    13                            DatagramPacket dp = new DatagramPacket(b, b.length,InetAddress.getByName("localhost"),8080);
    14                            
    15                            //发送数据
    16                            ds.send(dp);
    17                            
    18                            //关闭资源
    19                            ds.close();
    20             }
    21 }

    第八讲:网络编程(Udp-接收端)

    一,Udp 的 Socket 服务建立步骤。

      1. 建立DatagramSocket和DatagramPacket对象。
      2. 建立发送端(建立UDPSocket服务,在此无需指定端口,也可以将端口加入。如果不指定的话,系统会随机分配一个端口,如第一次运行时端口为1093,那么第二次就会顺延为1094,再运行会一直顺延,因为之前的端口还没有得到释放,所以会顺延端口号值。),接受端(定义UDPSocket服务。通常会监听一个端口,其实就是给这个接收网路应用程序定义数字标识,方便于明确哪些数据过来该应用程序可以处理。)。
      3. 建立数据包。
      4. 调用Socket发送接收方法。
      5. 关闭Socket。

    二,代码练习:

     1 import java.net.DatagramPacket;
     2 import java.net.DatagramSocket;
     3 
     4 public class UdpRece {
     5             public static void main(String[] args) throws Exception{
     6                             
     7                             //定义接受端套接字
     8                             DatagramSocket ds = new DatagramSocket(10000);
     9                             
    10                             //定义字节数组,保存接受内瓤
    11                             byte buf[] = new byte[1024];
    12                             
    13                             //定义数据包,接受数据
    14                             DatagramPacket dp = new DatagramPacket(buf,buf.length);
    15                             
    16                             //接受数据
    17                             ds.receive(dp);
    18                             
    19                             //将字节构造成字符
    20                             String revece = new String(buf);
    21                             
    22                             //标记发送端的端口
    23                             int port = dp.getPort();
    24                             
    25                             //标记发送端的地址
    26                             String address =dp.getAddress().getHostAddress();
    27                             
    28                             //输出内容
    29                             System.out.println("address:"+address+"port"+port+"revece"+revece);
    30                             
    31             }
    32 }

    第九讲:网络编程(UDP-键盘录入方式数据)

    一,一个特殊的IP地址: 192.168.1.255   广播地址。

    二代码练习:

     1 import java.net.*;
     2 import java.io.*;
     3 
     4 
     5 public class UpdSend2 {
     6              public static void main(String[] args) throws Exception {
     7                          
     8                              //创建套接字对象
     9                              DatagramSocket ds = new DatagramSocket();
    10                              
    11                              //创建数组接收对象
    12                              byte b[] = new byte[1024];
    13                              
    14                              //接受键盘输入
    15                              System.in.read(b);
    16                              
    17                              //构建数据包
    18                              DatagramPacket dp = new DatagramPacket(b,b.length,InetAddress.getByName("127.0.0.1"),10001);
    19                              
    20                              //发送数据包
    21                              ds.send(dp);
    22                              
    23                              //关闭资源
    24                              ds.close();
    25             }
    26 }

    第十讲:网络编程(UDP-聊天)

     一,需求分析:

      编写一个聊天程序 有收数据的部分,和发数据的部分 这两部分需要同时执行 那就需要用到多线程技术 一个线程控制收,一个线程控制发

    二,思路分析:

    1. 接收端和发送端需要同时完成收发功能。
    2. 接受数据,发送数据应当封装到两个线程中。

    三,代码练习:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 
     5 //创建线程类,此类启动一个线程,执行在端口10001接受网络数据操作
     6 class MyRece implements Runnable{
     7     
     8     //覆盖run()方法
     9     @Override
    10     public void run(){
    11         
    12         //循环接受数据
    13         while (true){
    14            try {
    15                
    16                //创建套接字对象,在端口10001接受网络数据
    17                 DatagramSocket ds = new DatagramSocket(10001);
    18             
    19                 //存储接受内容
    20                 byte b[] = new byte[1024];
    21             
    22                 //创建数据包对象
    23                 DatagramPacket dp = new DatagramPacket(b,b.length);
    24             
    25                 //接受数据
    26                 ds.receive(dp);
    27                 
    28                 //打印接受到的数据
    29                 System.out.println("主机:"+dp.getAddress()+"发来:"+new String(dp.getData(),0,dp.getLength()));
    30                 
    31                 //判断是否关闭程序
    32                 if(dp.getData().toString().trim().equals("886"))
    33                     //当对放发送886程序结束
    34                     break;
    35             } catch (SocketException e) {
    36                 System.out.println("网络错误"+e.toString());
    37             }catch (IOException e){
    38                  System.out.println("IO错误"+e.toString());
    39             } 
    40             
    41         }
    42     }
    43 }
    44 
    45 
    46 //创建一个类启动一个线程,该线程实现发送用户从键盘输入的内容
    47 class MySend implements Runnable{
    48     
    49         //覆盖方法
    50         @Override
    51         public void run(){
    52             //循环接受发送
    53             while(true){
    54                 
    55                 try{
    56                     //创建套接字对象
    57                      DatagramSocket ds = new DatagramSocket();
    58                     
    59                     //创建缓冲输入流,从键盘接受数据
    60                     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    61                     
    62                     //存储键盘输入的一行数据
    63                     String line = null;
    64                     
    65                     //如果用户输入886 ,发送数据,并结束程序运行
    66                     if((line=br.readLine()).trim().equals("886")){
    67                         DatagramPacket dp = new DatagramPacket(line.getBytes(),line.getBytes().length,InetAddress.getByName("127.0.0.1"),10001);
    68                         
    69                         ds.send(dp);
    70                         break;
    71                     }
    72                     
    73                     //发送数据
    74                     DatagramPacket dp = new DatagramPacket(line.getBytes(),line.getBytes().length,InetAddress.getByName("127.0.0.1"),10001);
    75                     
    76                     ds.send(dp);
    77                         
    78                 }catch(IOException e){
    79                     System.out.println("IO异常"+e.toString());
    80                 } 
    81                 
    82             }
    83         }
    84 }
    85 public class ChatDemo {
    86                 public static void main(String[] args) {
    87                     
    88                     
    89                        //创建线程对象
    90                        Thread t1 = new Thread(new MyRece());
    91                        Thread t2 = new Thread(new MySend());
    92                        
    93                        //启动线程
    94                        t1.start();
    95                        t2.start();
    96                 }
    97 }

    第十一讲:网络编程(TCP传输)

    一,TCP传输过程。

      1. 建立,Socket(客户端) 和ServerSocket(服务端,服务端需要明确它要处理的数据是从哪个端口进入的。)。=====因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,再通过该通道进行数据的传输。===
      2. 通过Socket中的IO流进行数据的传输。
      3. 关闭Socket。
      4. 客户端和服务器端是两个独立的应用程序。

    二,涉及道的类了解:

    1. Socket: 
      1. 定义:public class Socket extends Object    此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
      2. 构造方法:public Socket()          通过系统默认类型的 SocketImpl 创建未连接套接字                ==注:创建空参数的客户端对象,一般用于服务端接收数据==
      3. 构造方法:public Socket(String host, int port) throws UnknownHostException, IOException     创建一个流套接字并将其连接到指定主机上的指定端口号。
      4. 方法:public void bind(SocketAddress bindpoint) throws IOException    将套接字绑定到本地地址。如果地址为 null,则系统将挑选一个临时端口和一个有效本地地址来绑定套接字。
      5. 方法:public InetAddress getInetAddress()     返回套接字连接的地址。
      6. 方法:public int getPort()                               返回此套接字连接到的远程端口。
      7. 方法:public InetAddress getLocalAddress()   获取套接字绑定的本地地址。
      8. 方法:public int getLocalPort()                      返回此套接字绑定到的本地端口。
      9. 方法:public InputStream getInputStream() throws IOException  返回此套接字的输入流。
      10. 方法:public OutputStream getOutputStream() throws IOException   返回此套接字的输出流。
    2. ServerSocket:
      1. 类的定义:public class ServerSocket extends Object    此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
      2. 构造方法:public ServerSocket() throws IOException   创建非绑定服务器套接字。
      3. 构造方法:public ServerSocket(int port) throws IOException   创建绑定到特定端口的服务器套接字。
      4. 方法:public Socket accept() throws IOException    侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
      5. 方法:public void bind(SocketAddress endpoint) throws IOException   将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
      6. 方法:public InetAddress getInetAddress()         返回此服务器套接字的本地地址。将此套接字绑定到的地址;如果套接字是未绑定的,则返回 null
      7. 方法:public int getLocalPort()                           返回此套接字在其上侦听的端口。此套接字侦听的端口号;如果尚未绑定套接字,则返回 -1。

    三,思路分析:

    客户端:

            通过查阅Socket对象的API文档,发现在该对象在建立时,就可去连接指定主机,因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,再通过该通道进行数据的传输。

             1)创建Socket服务,并指定要连接的主机端口。通路一建立,就会产生Socket流(包括输入流和输出流),通过方法获取。========注:如果连接失败,会出现异常。连接成功,说明客户端与服务端建立了通道,之后即可以通过IO流交换数据。==========

             2)为了发送数据,应获取Socket中的输出流,如果要接收服务端的反馈信息,还需要获取Socket的输入流

             3)通过输出流的write()方法将要发送的数据写入到流中

             4)关闭Socket流资源

    服务端:

            服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。需监听一个端口。

             1)建立服务端的Socket服务,并监听一个端口。通过ServerSocet带端口参数的构造函数

             2)获取连接过来的客户对象,通过ServerSocket的accept()方法,此方法是阻塞式的,如果服务端没有连接到就会一直等待

             3)客户端如果发过来数据,则服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过来的数据,并输出到指定目的地。当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。

             4)关闭服务端(可选)。一般服务端是常开的,因为在实际应用中,随时有客户端在请求连接和服务。但这里需要定时关闭客户端对象流,避免某一个客户端长时间占用服务器端。

    四,代码练习:

    服务器端:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 
     5 //创建TCP服务器端,接受消息
     6 public class TCPServ {
     7                 public static void main(String[] args) {
     8                             
     9                         try {
    10                             
    11                             //创建服务器端套接字,在指定端口监听
    12                             ServerSocket ss = new ServerSocket(20000);
    13                             
    14                             //获得接收到的套接字的输入流
    15                             InputStream is = ss.accept().getInputStream();
    16                             
    17                             //存储数据
    18                             byte b[] = new byte[1024];
    19                             
    20                             //读入数据
    21                             is.read(b);
    22                             s.close();
    23                             //打印
    24                             System.out.println(new String(b,0,b.length));
    25                             
    26                         } catch (IOException e) {
    27                             // TODO Auto-generated catch block
    28                             e.printStackTrace();
    29                         } 
    30                 }
    31 }

    客户端:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 
     5 //创建客户端,以TCP方式连接到远程服务器
     6 class TCPClient {
     7             public static void main(String[] args) {
     8                 
     9                 
    10                 try {
    11                     
    12                     //创建客户端套接字,连接到制定主机的20000端口上
    13                     Socket s = new Socket(InetAddress.getByName("202.206.154.123"), 20000);
    14                     
    15                     //获得到远端主机的输出流
    16                     OutputStream out = s.getOutputStream();
    17                     
    18                     //输出数据
    19                     out.write("您好".getBytes());
    20                     //关闭资源
    21                     s.close();
    22                 } catch (UnknownHostException e) {
    23                     System.out.println("为找到主机"+e.toString());
    24                 } catch (IOException e) {
    25                     System.out.println("IO异常"+e.toString());
    26                 }
    27             }
    28 }

    第十二讲:网络编程(TCP传输2)

    一,练习:需求分析:客户端给服务端发送数据,服务端收到后,给客户端反馈信息

    二,代码练习:

    客户端:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 
     5 //创建客户端,以TCP方式连接到远程服务器
     6 class TCPClient {
     7             public static void main(String[] args) {
     8                 
     9                 
    10                 try {
    11                     
    12                     //创建客户端套接字,连接到制定主机的20000端口上
    13                     Socket s = new Socket(InetAddress.getByName("202.206.154.123"), 20000);
    14                     
    15                     //获得到远端主机的输出流
    16                     OutputStream out = s.getOutputStream();
    17                     
    18                     //输出数据
    19                     out.write("您好".getBytes());
    20                     
    21                     
    22                     //接受服务端消息
    23                     byte b[] = new byte[1024];
    24                     
    25                     //获取输入流
    26                     InputStream in = s.getInputStream();
    27                     
    28                     //标记接受数据量
    29                     int len=0;
    30                     
    31                     //读入数据
    32                     len=in.read(b);
    33                     
    34                     //输出数据
    35                     System.out.println(new String(b,0,len));
    36                     //关闭资源
    37                     s.close();
    38                 } catch (UnknownHostException e) {
    39                     System.out.println("为找到主机"+e.toString());
    40                 } catch (IOException e) {
    41                     System.out.println("IO异常"+e.toString());
    42                 }
    43             }
    44 }

    服务器端:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 
     5 //创建TCP服务器端,接受消息
     6 public class TCPServ {
     7                 public static void main(String[] args) {
     8                             
     9                         try {
    10                             
    11                             //创建服务器端套接字,在指定端口监听
    12                             ServerSocket ss = new ServerSocket(20000);
    13                             
    14                             Socket s = ss.accept();
    15                             //获得接收到的套接字的输入流
    16                             InputStream is = s.getInputStream();
    17                             
    18                             //存储数据
    19                             byte b[] = new byte[1024];
    20                             
    21                             //读入数据
    22                             is.read(b);
    23                             
    24                             //打印
    25                             System.out.println(new String(b,0,b.length));
    26                             
    27                             //获取输出流
    28                             OutputStream out = s.getOutputStream();
    29                             
    30                             //向客户端写入数据
    31                             out.write("客户端你也好".getBytes());
    32                             
    33                             //关闭资源
    34                             s.close();
    35                             
    36                         } catch (IOException e) {
    37                             // TODO Auto-generated catch block
    38                             e.printStackTrace();
    39                         } 
    40                 }
    41 }

    第一十三讲:网络编程(TCP练习)

    一,需求分析:

                    建立一个文本转换服务器, 客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端 ,而且客户端可以不断的进行文本转换。当客户端输入over时,转换结束 。

    二,操作步骤:

      1. 建立服务。
      2. 获取键盘输入。
      3. 将数据发给服务端。
      4. 接受服务端返回的数据。
      5. 关闭资源。

    ==============特别注意:如果使用字符缓冲区,写入完毕后,需要加入换行和刷新====================

    三,代码练习:

     客户端:

     1 import java.net.*;
     2 import java.io.*;
     3 public class TCPClient {
     4                 public static void main(String[] args) {
     5                             
     6                             //创建套接字连接服务器
     7                             Socket s = null;
     8                             
     9                             //获取输出流
    10                             OutputStream out = null;
    11                             
    12                             //获取输入流
    13                             InputStream is = null;
    14                             
    15                             
    16                             try {
    17                                 s = new Socket(InetAddress.getByName("127.0.0.1"),10000);
    18                                 
    19                                 out = s.getOutputStream();
    20                                 
    21                                 is = s.getInputStream();
    22                             } catch (UnknownHostException e) {
    23                                 // TODO Auto-generated catch block
    24                                 e.printStackTrace();
    25                             } catch (IOException e) {
    26                                 // TODO Auto-generated catch block
    27                                 e.printStackTrace();
    28                             }
    29                             
    30                              
    31                             
    32                             //字符缓冲流增加效率
    33                             BufferedReader brr = new BufferedReader(new InputStreamReader(is));
    34                             
    35                             BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
    36                             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    37                             
    38                             try{
    39                             //循环发送数据接收数据
    40                             while(true){
    41                                 
    42                                 //接收读入内容
    43                                  String line = null;
    44                                  
    45                                  //读入数据
    46                                  line = br.readLine();
    47                                  
    48                                  //写出数据
    49                                  bw.write(line);
    50                                  
    51                                  //换行
    52                                  bw.newLine();
    53                                  
    54                                  //刷新
    55                                  bw.flush();
    56                                  
    57                                  if("over".equals(line))
    58                                      break;
    59                                  line=brr.readLine();
    60                                 
    61                                  System.out.println(line);
    62                             }
    63                             s.close();
    64                             }catch (Exception e){
    65                                 System.out.println(e.toString());
    66                             }
    67                 }
    68 }            

    服务器端:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 public class TCPServ {
     5             public static void main(String[] args)   {
     6                 
     7                         //创建服务器端套接字,在端口10000监听
     8                         ServerSocket ss = null;
     9                         
    10                         //获取与客户端关联的 Socket
    11                         Socket s = null;
    12                         
    13                         //获取到客户端的输入流
    14                         InputStream is = null;
    15                         
    16                         OutputStream out =null;
    17                         
    18                         try {
    19                             ss = new ServerSocket(10000);
    20                             
    21                             s = ss.accept();
    22                             
    23                             out = s.getOutputStream();
    24                             is = s.getInputStream();
    25                         } catch (IOException e) {
    26                             // TODO Auto-generated catch block
    27                             e.printStackTrace();
    28                         }
    29                         
    30                         
    31                         
    32                         
    33                         
    34                         //使用字符缓冲流提高效率
    35                         BufferedReader br = new BufferedReader(new InputStreamReader(is));
    36                         
    37                         //字符缓冲流
    38                         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
    39                         
    40                         
    41                     try{
    42                         //循环接受客户端消息
    43                         while(true){
    44                             
    45                             //接受客户端内容
    46                             String line = null;
    47                             
    48                             //读入数据
    49                             line = br.readLine();
    50                             
    51                             //判断是否结束
    52                             if("over".equals(line))
    53                                 break;
    54                             
    55                             //向客户端写入数据
    56                             bw.write(line.toUpperCase());
    57                             
    58                             //换行
    59                             bw.newLine();
    60                             
    61                             //刷新
    62                             bw.flush();
    63                         }
    64                         ss.close();
    65                     }catch(Exception e){
    66                         System.out.println(e.toString());
    67                     }
    68             }
    69 }

    第一十四讲:网络编程(TCP复制文件)

    一,注意的问题:

      1. 因为客户端将数据发送完毕后,服务端仍然在等待这读取数据,并没有收到结束标记,就会一直等待读取。 
      2. 上个问题解决后,收到的不是指定信息而是null,是因为服务端写入数据后,需要刷新,才能将信息反馈给客服端。

    二,解决办法:

      1. 定义结束标记,先将结束标记发送给服务端,让服务端接收到结束标记,然后再发送上传的数据。但是这样定义可能会发生定义的标记和文件中的数据重复,而导致提前结束。
      2. 定义时间戳,由于时间是唯一的,在发送数据前,先获取时间,发送完后在结尾处写上相同的时间戳,在服务端,接收数据前先接收一个时间戳,然后在循环中判断时间戳以结束标记。
      3. 通过socket方法中的shutdownOutput(),关闭输入流资源,从而结束传输流,以给定结束标记。通常用这个方法。 

    三,代码练习

    客户端软件:

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 public class TextClient {
     5                 public static void main(String[] args) {
     6                                 
     7                     
     8                                 //创建客户端套接字
     9                                 Socket s = null;
    10                                 
    11                                 //输出流,输入流对象声明
    12                                 InputStream is = null;
    13                                 
    14                                 OutputStream os = null;
    15                                 
    16                                 FileInputStream fis = null;
    17                                 
    18                                 //标识文件
    19                                 String filename = "E:/sysinfo.txt";
    20                                 
    21                                 File file = new File(filename);
    22                                 
    23                                 
    24                                 //实例化对象引用
    25                                 try{
    26                                     s = new Socket(InetAddress.getLocalHost(),10000);
    27                                     
    28                                     is = s.getInputStream();
    29                                     
    30                                     os = s.getOutputStream();
    31                                     
    32                                     
    33                                     //判断文件是否存在
    34                                     if(!file.exists())
    35                                         System.out.println("文件不存在");
    36                                     else {
    37                                         fis = new FileInputStream(file);
    38                                     }
    39                                 }catch(Exception e){
    40                                     System.out.println(e.toString());
    41                                 }
    42                                 
    43                                 
    44                                 //字符缓冲刘提高操作效率
    45                                 BufferedReader br_file = new BufferedReader(new InputStreamReader(fis));
    46                                 BufferedReader br_net = new BufferedReader(new InputStreamReader(is));
    47                                 
    48                                 //获得服务端输出流
    49                                 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
    50                                 
    51                                 try{
    52                                     String line = null;
    53                                     
    54                                     //循环读取文件并发送到服务器端
    55                                     while ((line=br_file.readLine())!=null){
    56                                         
    57                                         //写入一行字符
    58                                         bw.write(line);
    59                                         
    60                                         //写入换行符
    61                                         bw.newLine();
    62                                         
    63                                         //刷新输出流
    64                                         bw.flush();
    65                                     }
    66                                     
    67                                     //写入结束标志
    68                                     bw.write("end");
    69                                     bw.newLine();
    70                                     bw.flush();
    71                                     
    72                                     //获取服务端响应
    73                                     line = br_net.readLine();
    74                                     
    75                                     System.out.println(line);
    76                                 }catch(IOException e){
    77                                     System.out.println(e.toString());
    78                                 }
    79                 }
    80 }

     

    服务端代码:

     

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 public class TextServ {
     5                 public static void main(String[] args) {
     6                             
     7                             //创建服务端套接字
     8                             ServerSocket ss = null;
     9                             
    10                             //接受客户端
    11                             Socket s = null;
    12                             
    13                             ////客户端输入流
    14                             InputStream is = null;
    15                             
    16                             //客户端输出流
    17                             OutputStream os = null;
    18                             
    19                             //定义文件
    20                             File file = new File("E:/rever.txt");
    21                             
    22                             //定义文件输入流
    23                             FileOutputStream fos = null;
    24                             
    25                             //实例化对象
    26                             try{
    27                                 ss = new ServerSocket(10000);
    28                                 
    29                                 s = ss.accept();
    30                                 
    31                                 is = s.getInputStream();
    32                                 
    33                                 os = s.getOutputStream();
    34                                 
    35                                 fos = new FileOutputStream(file);
    36                             }catch(Exception e){
    37                                 System.out.println(e.toString());
    38                             }
    39                             
    40                             //字符缓冲刘提高效率
    41                             BufferedReader br = new BufferedReader(new InputStreamReader(is));
    42                             
    43                             //缓冲输出流。提高效率
    44                             BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
    45                             
    46                             
    47                             BufferedWriter bw_file = new BufferedWriter(new OutputStreamWriter(fos));
    48                             
    49                             //异常处理
    50                             try{
    51                                 
    52                                 //接受读入一行字符串
    53                                 String line = null;
    54                                 
    55                                 //循环读取
    56                                 while((line=br.readLine())!=null){
    57                                     //判断是否结束
    58                                     if("end".equals(line))
    59                                         break;
    60                                     
    61                                     //保存到本地文件
    62                                       bw_file.write(line);
    63                                       
    64                                       //写入换行符
    65                                       bw_file.newLine();
    66                                       
    67                                       //刷新输出流
    68                                       bw_file.flush();
    69                                 }
    70                                 
    71                                 //给出提示
    72                                 bw.write("写入成功");
    73                                 
    74                                 //写入换行符
    75                                   bw.newLine();
    76                                   
    77                                   //刷新
    78                                   bw.flush();
    79                             }catch(Exception e){
    80                                 System.out.println(e.toString());
    81                             }
    82                             
    83                 }
    84 }

     

     

     
  • 相关阅读:
    pl/sql配置-本地不安装oracle-登录pl/sql
    js中查看js对象的属性
    eos中nui提交表单
    Window clearTimeout() 方法与setTimeout
    小程序---app.json文件的配置,全局的,对所有页面都适用
    css--加载中样式
    Vue+axios请求本地json
    vue中通过方法返回data中的对象是这个{__ob__: Observer},怎么处理 呢???
    解决 canvas 绘图在高清屏中的模糊问题
    总结:活动类开发必知必会
  • 原文地址:https://www.cnblogs.com/xiaochongbojue/p/4055211.html
Copyright © 2020-2023  润新知