J o u rna l o f W uha n In s titu te o f Educa tio na l S c ie nce VOL. 4 , NO. 4. 2006 用 Java实现基于 TCP / IP协议的网络通信程序 刘 嵩 [摘要 ] 随着互联网的飞速发展 ,程序开发已经由早期开发单机程序过渡到网络互联 的程序开发 。 Java 语言提供了一套功能强大的 AP I(应用编程接口 )来实现网络编程所需 的网络通信功能 。这套 AP I使 Java 程序员不用考虑复杂的网络协议以及底层的数据传 输方式 ,而直接用面向对象的思想来实现网络传输 。 [关键词 ] JAVA; 网络 ; SOCKET; CL IENT / SERVER [作者简介 ]刘嵩 : 武汉软件职业学院教师 。 (武汉 430205 ) 随着互联网的普及 ,程序开发过程中不可避 程之间进行 , 通信完毕关闭此联接过程 。使用无 免的要求实现网络互连通信功能 。网络上的系统 联接方式时其系统开销比无联接方式小 , 但通信 结构多为客户端 /服务器模式 ,服务器端负责数据 链路提供了不可靠的数据报服务 , 不能保证信源 和图像等的存储 、 维护 、 管理以及传递 ,客户端则负 所传输的数据一定能够到达信宿 。在该方式下 , 责人机界面的操作 、 送出需求及显示收回的数据 。 通信双方不必创建一个联接过程和建立一条通讯 下面介绍一下如何使用 Java来进行网络编程 : 链路 ,网络通信操作在不同的主机和进程之间转 发进行 。 TCP / IP系统中的端口号是一个 16 位的 一、 基本原理 数字 ,它的范围是 0 ~65535。实际上 , 小于 1024 socket是指在一个特定编程模型下进程间通 的端口号保留给预定义的服务 , 而且除非要和那 信链路的端点 。一个 socket包括两个流 : 一个输 些服务之一进行通信 (例如 telnet, SM TP 邮件和 入流和一个输出流 。如果一个进程要通过网络向 ftp 等 ) ,否则你不应该使用它们 。客户和服务器 另一个进程发送数据 , 只需简单地写入与 socket 必须事先约定所使用的端口 。如果系统两部分所 相关联的输出流 。一个进程通过从与 socket相关 使用的端口不一致 ,那就不能进行通信 。 联的输入流读来读取另一个进程所写的数据 。如 果要建立连接 , 一台机器必须运行一个进程来等 二、 实现方法 待连接 ,而另一台机器必须试图到达第一台机器 。 Java 中输入 /输出流概念 : 过滤流 Data Input2 这和电话系统类似 ; 一方必须发起呼叫 ,而另一方 Stream 和 DataOutputStream 除了分别作为 FilterIn2 在此时必须等待电话呼叫 。 socket通信机制提供 putStream 和 FilterOutputStream 的子类外 , 还分别 了两种通讯方式 : 有联接和无联接方式 ,分别面向 实现 了 接 口 Data Input 和 DataOutput。接 口 Da2 不同的应用需求 。使用有联接方式时 , 通信链路 ta Input 中定义的方法主要包括从流中读取基本 提供了可靠的 , 全双工的字节流服务 。在该方式 类型的数据 、 读取一行数据 、 或者读取指定长度的 下 ,通信双方必须创建一个联接过程并建立一条 字节数 ,如 readBoolean ( ) read Int ( ) 、readL ine ( ) 、 通讯链路 ,以后的网络通信操作完全在这一对进 readFully ( )等 。接口 DataOutput中定义的方法主 武汉市教育科学研究院学报 67 VOL. 4 , NO. 4. 2006 J o u rna l o f W uha n In s titu te o f Educa tio na l S c ie nce 要是向流中写入基本类型的数据或者写入一定长 OutputStream os = s. getO utputStream ( ) 度的字节数组 ,如 w riteChar ( ) 、w riteDouble ( ) Da2 / /省略从输入流读取数据代码 ta InputStream 可以从所连接的输入流中读取与机 os. close ( ) ; 器无关的基本类型数据 , 用以实现一种独立于具 is. close ( ) ; 体平台的输入方式 ; Data InputStream 可以向所连 s. close ( ) ; 接的输出流写入基本类型的数据 。 (二 )服务器端的编程流程 多线程使应用程序可以同时进行不同的操作 打开 ServerSocket创建一个服务器型套接字 处理不同的事件 。在多线程机制中 , 不同的线程 和一个普通套接字 , 服务器型套接字在指定端为 处理不同的任务 ,他们之间互不干涉 ,不会由于一 客户端请求的 Socket服务 ; 使用 ServerSocket类的 处等待影响其他部分 , 这样容易实现网络上的实 accep t ( )方法使服务器型套接字处于监听状态并 时交互操作 。 Java 程序可以有多个执行线程 , 如 把监听结果返回给普通套接字 ; 为该普通套接字 可以让一个线程进行复杂的计算 , 而让另一个线 创建输入和输出流 ; 从输入和输出流中读入或写 程与用户进行交互 , 这样用户可以在不中断计算 入字节流 ,进行相应的处理 ,并将结果返回给客户 线程的前提下与系统进行交互 。多线程保证了较 端 ; 在客户端和服务器工作结束后关闭所有的对 高的执行效率 。 象 ,如服务器型的套接字 , 普通套接字 , 输入和输 出流 。正是由于 Java 系统具有基于 Socket 的灵 三、 具体实现 活通信机制 ,因而其应用程序能自由地打开和访 App lication 同 App let的通信 ,两端通过 Sock2 问网络上的对象 ,就象在本地文件系统中一样 。 et机制进行连接 ,通信过程如图 1 所示 : 下面的代码在 4331 端口创建了一个 Server2 Socket对象负责处理客户端的套接字请求 , 为每 一个用户请求套接字启动一个新的线程 , 并且通 过处理请求得到的套接字对象获取输入输出流进 行数据传输 。 try{ server = new ServerSocket ( 4331 ) ; } catch ( IO Excep tion e1 ) { System. out. p rintln (“正 在 监 听 ”) ; / / Ser2 verSocket对象不能重复创建 (一 )客户端的编程流程 打开 Socket,新建一个套接字 ,为套接字建立 try{ you = server. accep t ( ) ; / /等待用户连接 } 一个输入和输出流 ; 根据服务器协议从套接字读 catch ( IO Excep tion e ) { } 出或向套接字写入 ,清除套接字和输入 /输出流 。 if ( you! = null) { 下面的代码创建了一个服务程序主机地址为 198. 163. 227. 6,端口号为 4331 的 Socket对象 , new Server_thread ( you ) . start ( ) ; / /为每个客 户启动一个专门的线程 } 然后从这个新创建的 Socket对象中获取输入输出 ... ... 流进行数据传输 ,然后再关闭流和 Socket对象 。 class Server_thread extends Thread{ Socket s = new Socket (“198. 163. 227. 6 ”, 4331 ) ; InputStream is = s. getInputStream ( ) ; 68 武汉市教育科学研究院学报 Socket socket; Connection Con = null; Statement Stm t = null; DataOutputStream out = null; (下转第 71 页 ) J o u rna l o f W uha n In s titu te o f Educa tio na l S c ie nce VOL. 4 , NO. 4. 2006 这样得到了 vp tr这个指针 , 然后用一个 unsigned ( 3 f) ( ) ; char指针运算偏移量 , 得到的结果再次输入 getp delete p; } ( ) ,这次得到的就应该是正确的函数体的位置 运行结果为 : 了。 A: : fun1 ( ) 那么它到底能不能正确工作呢 ? 我们修改 main ( ) 来测试一下 : int main ( ) A: : fun2 ( ) B ase: : fun3 ( ) 通过上述方法 , 我们获取了对象的 VPTR , 在 {B ase 3 p = new A; 它的体外执行了它的虚函数 , 也对 VPTR 在多态 fun f = getfun ( p , 0 ) ; 中的应用有了深刻的认识 . 相信读者以后遇到运 ( 3 f) ( ) ; 行时的多态感觉会好多了吧 。 f = getfun ( p , 1 ) ; ( 3 f) ( ) ; 〔责任编辑 : 陈光兰 〕 f = getfun ( p , 2 ) ; (上接第 68 页 ) Data InputStream in = null; i Server_thread ( Socket t) 有主机 IP地址或主机名参数 。 (二 )连接建立好之后应确定输入和输出流 。 { socket = t; 起 初 程 序 中 用 的 是 Data InputStream 和 Print2 try { / /通过套接字获取输入输出流 Stream , 结果只能传输英文 , 传输中文时产生乱 in = new Data InputStream ( socket. getInput2 码 ,将 PrintStream 改为 DataOutputStream , 使用 re2 Stream ( ) ) ; out = new DataOutputStream ( socket. getO utput2 Stream ( ) ) ; } catch ( IO Excep tion e ) { } } Java 语 言 为 我 们 提 供 了 强 大 的 网 络 开 发 adUTF ( ) 和 w riteUTF ( ) 方法后 , 中文传输问题得 到解决 。 (三 )如果一个使用某端口的程序没有关闭 , 另一个程序就不能使用这个端口 。 参考文献 : AP I,使我们能够通过简单的面向对象的编程思想 [ 1 ]B ruce Eckel. Java编程思想 [M ]. 机械工业出版社 来通过 TCP / IP 协议进行复杂的网络通信 。但是 [ 2 ] Cay S. Horstm ann, Gary Cornell. Java 2 核心技术 (第 6 版 ) 在实际运用中还需要注意以下问题 : (一 )在建立 Socket连接时 , 两端的端口号必 须设为一致 , 否则建立不了连接 。服务器端必须 卷 I: 基础知识 [M ]. 机械工业出版社 〔责任编辑 : 陈光兰 〕 武汉市教育科学研究院学报 71