zoukankan      html  css  js  c++  java
  • 网络编程——第一部分

     

    新博客地址: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 }

     

     

     
  • 相关阅读:
    UVA 1025 A Spy in the Metro DP水题
    ZOJ 3814 Sawtooth Puzzle BFS
    ZOJ 3816 Generalized Palindromic Number
    UVA 10859 Placing Lampposts 树形DP
    UVA 11825 Hackers' Crackdown 状压DP
    POJ 2887 Big String 线段树 离线处理
    POJ 1635 Subway tree systems Hash法判断有根树是否同构
    BZOJ 3110 k大数查询 & 树套树
    sdoi 2009 & 状态压缩
    来自于2016.2.24的flag
  • 原文地址:https://www.cnblogs.com/xiaochongbojue/p/4055211.html
Copyright © 2011-2022 走看看