文档章节

Java中的网络编程

乐在克里特
 乐在克里特
发布于 2017/02/23 14:57
字数 2826
阅读 11
收藏 0

一、网络通讯方式

在现有的网络中,网络通讯的方式主要有两种:

    1.TCP(传输控制协议)方式
    2.UDP(用户数据报协议)方式
    为了方便理解这两种方式,还是先来看一个例子。大家使用手机时,向别人传递信息时有两种方式:拨打电话和发送短信。使用拨打电话的方式可以保证将信息传递给别人,因为别人接听电话时本身就确认接收到了该信息。而发送短信的方式价格低廉,使用方便,但是接收人有可能接收不到。

在网络通讯中,TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据。而UDP方式就类似于发送短信,使用这种方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端无法获得。

       这两种传输方式都是实际的网络编程中进行使用,重要的数据一般使用TCP方式进行数据传输,而大量的非核心数据则都通过UDP方式进行传递,在一些程序中甚至结合使用这两种方式进行数据的传递。

        由于TCP需要建立专用的虚拟连接以及确认传输是否正确,所以使用TCP方式的速度稍微慢一些,而且传输时产生的数据量要比UDP稍微大一些。

       关于网络编程的基础知识就介绍这么多,如果需要深入了解相关知识请阅读专门的计算机网络书籍,下面开始介绍Java语言中网络编程的相关技术。

二、网络编程步骤

       按照前面的基础知识介绍,无论使用TCP方式还是UDP方式进行网络通讯,网络编程都是由客户端和服务器端组成。当然,B/S结构的编程中只需要实现服务器端即可。所以,下面介绍网络编程的步骤时,均以C/S结构为基础进行介绍。

         说明:这里的步骤实现和语言无关,也就是说,这个步骤适用于各种语言实现,不局限于Java语言。

2.1 客户端网络编程步骤

       客户端(Client)是指网络编程中首先发起连接的程序,客户端一般实现程序界面和基本逻辑实现,在进行实际的客户端编程时,无论客户端复杂还是简单,以及客户端实现的方式,客户端的编程主要由三个步骤实现:

      (1)建立网络连接
      客户端网络编程的第一步都是建立网络连接。在建立网络连接时需要指定连接到的服务器的IP地址和端口号,建立完成以后,会形成一条虚拟的连接,后续的操作就可以通过该连接实现数据交换了。
      (2)交换数据
      连接建立以后,就可以通过这个连接交换数据了。交换数据严格按照请求响应模型进行,由客户端发送一个请求数据到服务器,服务器反馈一个响应数据给客户端,如果客户端不发送请求则服务器端就不响应。
      根据逻辑需要,可以多次交换数据,但是还是必须遵循请求响应模型。
      (3)关闭网络连接
      在数据交换完成以后,关闭网络连接,释放程序占用的端口、内存等系统资源,结束网络编程。
      最基本的步骤一般都是这三个步骤,在实际实现时,步骤2会出现重复,在进行代码组织时,由于网络编程是比较耗时的操作,所以一般开启专门的现场进行网络通讯。

2.2 服务器端网络编程步骤

       服务器端(Server)是指在网络编程中被动等待连接的程序,服务器端一般实现程序的核心逻辑以及数据存储等核心功能。服务器端的编程步骤和客户端不同,是由四个步骤实现,依次是:

       (1)监听端口
       服务器端属于被动等待连接,所以服务器端启动以后,不需要发起连接,而只需要监听本地计算机的某个固定端口即可。
       这个端口就是服务器端开放给客户端的端口,服务器端程序运行的本地计算机的IP地址就是服务器端程序的IP地址。
       (2)获得连接
       当客户端连接到服务器端时,服务器端就可以获得一个连接,这个连接包含客户端的信息,例如客户端IP地址等等,服务器端和客户端也通过该连接进行数据交换。
       一般在服务器端编程中,当获得连接时,需要开启专门的线程处理该连接,每个连接都由独立的线程实现。
       (3)交换数据
       服务器端通过获得的连接进行数据交换。服务器端的数据交换步骤是首先接收客户端发送过来的数据,然后进行逻辑处理,再把处理以后的结果数据发送给客户端。简单来说,就是先接收再发送,这个和客户端的数据交换数序不同。
       其实,服务器端获得的连接和客户端连接是一样的,只是数据交换的步骤不同。
       当然,服务器端的数据交换也是可以多次进行的。
       在数据交换完成以后,关闭和客户端的连接。
       (4)关闭连接
       当服务器程序关闭时,需要关闭服务器端,通过关闭服务器端使得服务器监听的端口以及占用的内存可以释放出来,实现了连接的关闭。
       其实服务器端编程的模型和呼叫中心的实现是类似的,例如移动的10086就是典型的呼叫中心,当一个用户拨打10086时,转接给一个专门的客服人员,由该客服实现和该用户的问题解决,当另外一个用户拨打10086时,则转接给另一个客服,实现问题解决,依次类推。

        在服务器端编程时,10086这个电话号码就类似于服务器端的端口号码,每个用户就相当于一个客户端程序,每个客服人员就相当于服务器端启动的专门和客户端连接的线程,每个线程都是独立进行交互的。

       这就是服务器端编程的模型,只是TCP方式是需要建立连接的,对于服务器端的压力比较大,而UDP是不需要建立连接的,对于服务器端的压力比较小罢了。

三、TCP编程

1.复用性较高的Socket客户端:

package tcp;
import java.io.*;
import java.net.*;
/**
 * 复用连接的Socket客户端
 * 功能为:发送字符串“Hello”到服务器端,并打印出服务器端的反馈
 */
public class MulSocketClient {
         public static void main(String[] args) {
                   Socket socket = null;
                   InputStream is = null;
                   OutputStream os = null;
                   //服务器端IP地址
                   String serverIP = "127.0.0.1";
                   //服务器端端口号
                   int port = 10000;
                   //发送内容
                   String data[] ={"First","Second","Third"};
                   try {
                            //建立连接
                            socket = new Socket(serverIP,port);
                            //初始化流
                            os = socket.getOutputStream();
                            is = socket.getInputStream();
                            byte[] b = new byte[1024];
                            for(int i = 0;i < data.length;i++){
                                     //发送数据
                                     os.write(data[i].getBytes());
                                     //接收数据
                                     int n = is.read(b);
                                     //输出反馈数据
                                     System.out.println("服务器反馈:" + new String(b,0,n));
                            }
                   } catch (Exception e) {
                            e.printStackTrace(); //打印异常信息
                   }finally{
                            try {
                                     //关闭流和连接
                                     is.close();
                                     os.close();
                                     socket.close();
                            } catch (Exception e2) {}
                   }
         }
}

复用性较高的ServerSocket:

package tcp;
import java.io.*;
import java.net.*;
/**
 * 复用连接的echo服务器
 * 功能:将客户端发送的内容反馈给客户端
 */
public class MulSocketServer {
         public static void main(String[] args) {
                   ServerSocket serverSocket = null;
                   Socket socket = null;
                   OutputStream os = null;
                   InputStream is = null;
                   //监听端口号
                   int port = 10000;
                   try {
                            //建立连接
                            serverSocket = new ServerSocket(port);
                            System.out.println("服务器已启动:");
                            //获得连接
                            socket = serverSocket.accept();
                            //初始化流
                            is = socket.getInputStream();
                            os = socket.getOutputStream();
                            byte[] b = new byte[1024];
                            for(int i = 0;i < 3;i++){
                                     int n = is.read(b);
                                     //输出
                                     System.out.println("客户端发送内容为:" + new String(b,0,n));
                                     //向客户端发送反馈内容
                                     os.write(b, 0, n);
                            }
                   } catch (Exception e) {
                            e.printStackTrace();
                   }finally{
                            try{
                                     //关闭流和连接
                                     os.close();
                                     is.close();
                                     socket.close();
                                     serverSocket.close();
                            }catch(Exception e){}
                   }
         }
}

在该示例代码中,也将数据发送和接收的逻辑写在了一个for循环内部,只是在实现时硬性的将循环次数

规定成了3次,这样代码虽然比较简单,但是通用性比较差。
以该服务器端代码实现为基础运行前面的客户端程序时,客户端的输出为:
服务器反馈:First
服务器反馈:Second
服务器反馈:Third

服务器端程序的输出结果为:
服务器已启动:
客户端发送内容为:First
客户端发送内容为:Second
客户端发送内容为:Third

2.服务器端支持多个客户端同时工作

package tcp;

import java.net.ServerSocket;
import java.net.Socket;
/**
 * 支持多客户端的服务器端实现
 */
public class MulThreadSocketServer {
         public static void main(String[] args) {
                   ServerSocket serverSocket = null;
                   Socket socket = null;
                   //监听端口号
                   int port = 10000;
                   try {
                            //建立连接
                            serverSocket = new ServerSocket(port);
                            System.out.println("服务器已启动:");
                            while(true){
                                     //获得连接
                                     socket = serverSocket.accept();
                                     //启动线程
                                     new LogicThread(socket);
                            }
                   } catch (Exception e) {
                            e.printStackTrace();
                   }finally{
                            try{
                                     //关闭连接
                                     serverSocket.close();
                            }catch(Exception e){}
                   }
         }
}

       在该示例代码中,实现了一个while形式的死循环,由于accept方法是阻塞方法,所以当客户端连接未到达时,将阻塞该程序的执行,当客户端到达时接收该连接,并启动一个新的LogicThread线程处理该连接,然后按照循环的执行流程,继续等待下一个客户端连接。这样当任何一个客户端连接到达时,都开启一个专门的线程处理,通过多个线程支持多个客户端同时处理。

       下面再看一下LogicThread线程类的源代码实现:

package tcp;

import java.io.*;
import java.net.*;
/**
 * 服务器端逻辑线程
 */
public class LogicThread extends Thread {
         Socket socket;
         InputStream is;
         OutputStream os;
         public LogicThread(Socket socket){
                   this.socket = socket;
                   start(); //启动线程
         }
        
         public void run(){
                   byte[] b = new byte[1024];
                   try{
                            //初始化流
                            os = socket.getOutputStream();
                            is = socket.getInputStream();
                            for(int i = 0;i < 3;i++){
                                     //读取数据
                                     int n = is.read(b);
                                     //逻辑处理
                                     byte[] response = logic(b,0,n);
                                     //反馈数据
                                     os.write(response);
                            }
                   }catch(Exception e){
                            e.printStackTrace();
                   }finally{
                            close();
                   }
         }
        
         /**
          * 关闭流和连接
          */
         private void close(){
                   try{
                            //关闭流和连接
                            os.close();
                            is.close();
                            socket.close();
                   }catch(Exception e){}
         }
        
         /**
          * 逻辑处理方法,实现echo逻辑
          * @param b 客户端发送数据缓冲区
          * @param off 起始下标
          * @param len 有效数据长度
          * @return
          */
         private byte[] logic(byte[] b,int off,int len){
                   byte[] response = new byte[len];
                   //将有效数据拷贝到数组response中
                   System.arraycopy(b, 0, response, 0, len);
                   return response;
         }
}

 

摘取开发中实际使用的部分:

http://www.cnblogs.com/springcsc/archive/2009/12/03/1616413.html

© 著作权归作者所有

共有 人打赏支持
乐在克里特
粉丝 15
博文 268
码字总数 394729
作品 0
杭州
程序员
一句话讲清楚什么是JavaEE

Java技术不仅是一门编程语言而且是一个平台。同时Java语言是一门有着特定语法和风格的高级的面向对象的语言,Java平台是Java语言编写的特定应用程序运行的环境。Java平台有很多种,很多的Jav...

qq58edeba279279
06/26
0
0
什么是Java语言?java语言简介

Java是由Sun Microsystems公司于1995年5月推出的Java程序设计语言(以下简称Java语言)和Java平台的总称。用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台、动态的W...

阿秀a
2010/10/19
0
0
从程序员走向java架构师的书籍推荐!

作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从。我想就我自己读过的技术书籍中挑选出来一些,按照学习的先后顺序,推荐给大家,特别是那些想...

欧阳海阳
07/16
0
0
五本值得一读的超棒Java电子书(附下载)

http://www.itwaka.com/ 网络上有很多关于Java的免费电子书,但是大多数都是过时的或者是不准确的。这是说的Java免费电子书是我收藏中最好的五本,它们在使用 Java编程语言的人群中是出名的,...

itwaka
2011/06/27
0
0
学习大数据需要Java基础吗?

近几年,很多人都听到过一个名词“大数据”也有一部分人选择学习了解大数据,那么大数据到底是什么,学习大数据需要有Java基础吗? 推荐一个大数据学习交流群 119599574每天晚上20:10都有一节...

大数据大咖
06/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JavaFX WebView概述,很强大,内置了类似Electron的功能

来自 Murali Billa JavaFX技术人员的主要成员 在本博客中,我们将了解JavaFX如何呈现网页及其主要的组件 - 即WebView JavaFX是: 用于创建和交付桌面应用程序的软件平台,以及可以在各种设备...

GuoMengyue
26分钟前
4
0
数据库监控系统小实现1

需求:通过java 去调取python 去目标数据库采集信息,然后插入到数据库,由前台UI显示出来,从而达到监控目的。 设计:通过java的Runtime.getRuntime().exec(args1)方法去调用python脚本,j...

hnairdb
29分钟前
1
0
spring boot logback-spring 配置 日志分文件

因为更规规范化,想将日志分文异常类型,分别存储起来,方便以后查询问题。 以下是 logback-spring.xml 配置: <?xml version="1.0" encoding="UTF-8"?><configuration scan="true"> ...

诺岚
30分钟前
3
0
OSChina 周三乱弹 —— 这下回去要被老婆挠死

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @andonny :分享Passenger的单曲《Let Her Go》 《The Importance of Being Idle》-Noel Gallagher/It's a Cover Up 手机党少年们想听歌,请使...

小小编辑
49分钟前
680
19
RedHat已更改其开源许可规则

对于编程圈外的人来说,软件许可证似乎并不重要,但是,在开源领域,开源许可是非常重要的。 因此,领先的Linux公司Red Hat宣布了一件大事,所有新的由Red Hat发起的使用GNU通用公共许可证(...

linuxCool
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部