java程序员菜鸟进阶一之java网络通信编程

一、网络通讯的两种方式

1、概述:网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据

2、TCP(传输控制协议)方式

             TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据

3、 UDP(用户数据报协议)方式

              UDP方式就类似于发送短信,使用这种方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端无法获得

4、两种方式的区别:

             TCP比UCP安全,TCP是可靠的传输协议,UCP是不可靠的传输协议,UCP的传输的有大小限制的,TCP的传输是无大小限制的

二、基于URL的网络编程

1、创建URL:通过java.net包中的类URL的构造方法来创建URL

           (1) public URL (String spec);
     通过一个表示URL地址的字符串可以构造一个URL对象
     URL urlBase=new URL("http://www. 263.net/")
       (2) public URL(URL context, String spec);
     通过基URL和相对URL构造一个URL对象。
     URL net263=new URL ("http://www.263.net/");
     URL index263=new URL(net263, "index.html")
       (3) public URL(String protocol, String host, String file);
     new URL("http", "www.gamelan.com", "/pages/Gamelan.net. html");
       (4) public URL(String protocol, String host, int port, String file);
     URL gamelan=new URL("http", "www.gamelan.com", 80, "Pages/Gamelan.network.html");

2、解析URL:一个URL对象生成后,其属性是不能被改变的,但是我们可以通过类URL所提供的方法来获取这些属性

                   public String getProtocol() /获取该URL的协议名。
            public String getHost() /获取该URL的主机名。
            public int getPort() /获取该URL的端口号,如果没有设置端口,返回-1。
            public String getFile()/ 获取该URL的文件名。
            public String getRef() /获取该URL在文件中的相对位置。
            public String getQuery()/ 获取该URL的查询信息。
            public String getPath() /获取该URL的路径
              public String getAuthority()/ 获取该URL的权限信息
            public String getUserInfo() /获得使用者的信息
            public String getRef()/获得该URL的锚

3、从URL中获得网络资源                

                URL url = new URL("http://www.baidu.com"); //获取url对象

                InputStream openStream();//通过url对象获取一个输入流

               //使用openStream得到一输入流并由此构造一个BufferedReader对象                                                                 BufferedReader br = new BufferedReader(new InputStreamReader( url.openStream()));

               String line = null;

              while(null != (line = br.readLine())){System.out.println(line);}br.close();

3、客户端与服务端的编程步骤

               客户端:建立网络连接——交换数据——关闭网络连接

               服务端:监听端口——建立网络连接——交换数据——关闭网络连接

三、TCP方式的网络编程

1、概述:Socket实质上提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的

2、客户端的编程步骤

 1) 建立Socket连接 
                Socket socket2 = new Socket(“www.sohu.com”,80);
        2)按照“请求-响应”模型进行网络数据交换
                在Java语言中,数据传输功能由Java IO实现,也就是说只需要从连接中获得输入流和输出流即可,然后将需要发送的数据写入连接对象的输出流中,在发送完成以后从输入流中读取数据即可。示例代码如下:
                OutputStream os = socket1.getOutputStream(); //获得输出流
                InputStream is = socket1.getInputStream();     //获得输入流
               这里获得的只是最基本的输出流和输入流对象,还可以根据前面学习到的IO知识,使用流的嵌套将这些获得到的基本流对象转换成需要的装饰流对象,从而方便数据的操作。
      3)关闭网络连接
               socket1.close();

3、服务端的编程步骤

       1)监听端口
                   ServerSocket ss = new ServerSocket(10000);
       2)获得连接
                  当有客户端连接到达时,建立一个和客户端连接对应的Socket连 接对象,从而释放客户端连接对于服务器端端口的占用
                  Socket socket = ss.accept();
                该代码实现的功能是获得当前连接到服务器端的客户端连接。需要说明的是accept和前面IO部分介绍的read方法一样,都是一个阻塞方法,也就是当无连接时,该方法将阻塞程序的执行,直到连接到达时才执行该行代码。另外获得的连接会在服务器端的该端口注册,这样以后就可以通过在服务器端的注册信息直接通信,而注册以后服务器端的端口就被释放出来,又可以继续接受其它的连接了。
       3)按照“请求-响应”模型进行网络数据交换
                  这里获得的Socket类型的连接就和客户端的网络连接一样了,只是服务器端需要首先读取发送过来的数据,然后进行逻辑处理以后再发送给客户端,也就是交换数据的顺序和客户端交换数据的步骤刚好相反
                   InputStream is = ss.getInputStream();     //获得输入流
                   OutputStream os = ss.getOutputStream(); //获得输出流
        4)关闭服务器端连接
                   ss.close();

四、HttpURLConnection类的使用

1、URL请求的类别: 
分为二类,GET与POST请求。二者的区别在于: 
     a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet, 
     b:) post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。 

2、URLConnection的对象问题: 
        URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro/index.jsp"); 
        URLConnection rulConnection = url.openConnection();// 此处的urlConnection对象实际上是根据URL的 
        请求协议(此处是http)生成的URLConnection类 的子类HttpURLConnection,故此处最好将其转化 为HttpURLConnection类型的对象,以便用到  HttpURLConnection更多的API.如下: 
        HttpURLConnection httpUrlConnection = (HttpURLConnection) rulConnection; 

3、 HttpURLConnection对象参数问题 
       设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在 http正文内,因此需要设为true, 默认情况下是false; 
              httpUrlConnection.setDoOutput(true); 
      设置是否从httpUrlConnection读入,默认情况下是true; 
             httpUrlConnection.setDoInput(true); 
      Post 请求不能使用缓存 
             httpUrlConnection.setUseCaches(false); 
      设定传送的内容类型是可序列化的java对象  (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException) 
            httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object"); 
       设定请求的方法为"POST",默认是GET 
           httpUrlConnection.setRequestMethod("POST"); 
       连接,从上述第2条中url.openConnection()至此的配置必须要在connect之前完成, 
           httpUrlConnection.connect(); 

4、 HttpURLConnection连接问题: 
           OutputStream outStrm = httpUrlConnection.getOutputStream(); 
           此处getOutputStream会隐含的进行connect(即:如同调用上面的connect()方法,所以在开发中不调用上述的connect()也可以)。 

5、 HttpURLConnection写数据与发送数据问题: 
         现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。 
                ObjectOutputStream objOutputStrm = new ObjectOutputStream(outStrm); 
         向对象输出流写出数据,这些数据将存到内存缓冲区中 
                objOutputStrm.writeObject(new String("我是测试数据")); 
         刷新对象输出流,将任何字节都写入潜在的流中(些处为ObjectOutputStream) 
                objOutputStm.flush(); 
         关闭流对象。此时,不能再向对象输出流写入任何数据,先前写入的数据存在于内存缓冲区中, 
         在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器 
               objOutputStm.close(); 
         调用HttpURLConnection连接对象的getInputStream()函数, 
         将内存缓冲区中封装好的完整的HTTP请求电文发送到服务端。 
         InputStream inStrm = httpConn.getInputStream();                                                                                                               注意:实际发送请求的代码段就在这里上边的httpConn.getInputStream()方法已调用,本次HTTP请求已结束,下边向对象输出流的输出已无意义, 既使对象输出流没有调用close()方法,下边的操作也不会向对象输出流写入任何数据.  因此,要重新发送数据时需要重新创建连接、重新设参数、重新创建流对象、重新写数据、 重新发送数据(至于是否不用重新这些操作需要再研究)                                                                                                                                                                                                   objOutputStm.writeObject(new String(""));                                                                                                                           httpConn.getInputStream(); 

6、总结:

         a:) HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。 
    无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。 
         b:) 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,对connection对象的一切配置(那一堆set函数) 都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。 
                 这些顺序实际上是由http请求的格式决定的。如果inputStream读操作在outputStream的写操作之前,会抛出例外: java.net.ProtocolException: Cannot write output after reading input....... 
       c:) http请求实际上由两部分组成, 
                      一个是http头,所有关于此次http请求的配置都在http头里面定义, 一个是正文content。connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,就必须把所有的配置准备好。 
          d:) 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求,正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值