`

3.服务器端读写消息实现

阅读更多

1.设定服务器顺循环等待:

    服务器不能只连接一个客户机就退出——你可以将ServerSocketaccept()方法放在一个循环中调用:进行一个客户机,当服务器与这个客户机通信完毕后,服务器就再次进入循环中,重新调用accept()方法等待下一客户机连接进入,代码示例如下:

while(true){

       Socket client=server.accept();//让服务器在while中等待:阻塞状态

     //从连接对象上得到输入输出流对象. . .

当然,如果你要控制服务器的启动和停止,硬编码while的条件为true可不是个好主意。

2.读取客户机字符串分析

   至此,我们知道了服务器创建的基本流程,但有一件事还没弄明白,一个字符串是如何通过网络被发送到客户机的?如何读取客户机发来的消息?

   发送字符串分析:

    请注意,发送字符串时,首先调用字符串的getBytes()方法,得到组成这个字符串的字节数组,发送出的实际上是这个字节数组。请测试如下代码,示例了在字符串和和字节数组之间的转换:

String s="Hello!";

       byte[] data=s.getBytes();

       for(int i=0;i<data.length;i++){

     System.out.println(i+"个字节是"+data[i]

     +" 二进制是:"+Integer.toBinaryString(data[i]));

       }

       //再将字节组转为字符串

       String src=new String(data);

System.out.println("生成的字符串是: "+src);

  运行后,输出的结果如下:

0个字节是72 二进制是:1001000

1个字节是101 二进制是:1100101

2个字节是108 二进制是:1101100

3个字节是108 二进制是:1101100

4个字节是111 二进制是:1101111

5个字节是33 二进制是:100001

生成的字符串是: Hello!

   我的目地只是要说明:字符串是由字节组成的,字节是二进制位组成的——在网络上发送的,其实是一个个字节(byte),或者说是组成每一个字节的一个二进制位(bit)从网络中读取信息时,情况也是一样的。从InputStream对象中,一次只能读到一个字节,然后,再将这些字节组装为一个String对象——前提是对方发送的是一串文本,而不是一张图片,如下代码:

public void setUpServer(int port){

       try{

     //建立绑定在指定端口上的服务器对象

     ServerSocket server=new  ServerSocket(port);

    System.out.println("服务器创建成功!"+port);

   while(true){ //让服务器循环等待

      Socket client=server.accept();

     //从连接对象上得到输入输出流对象

      OutputStream out=client.getOutputStream();

      InputStream ins=client.getInputStream();

      String s="你好,欢迎来javaKe.com\r\n";

        byte[] data=s.getBytes();//取得组成这个字符串的字节

           out.write(data); //用输出对象发送数据

          out.flush();//强制输出

          int in=0; //一个字节一个字节的读取客户机的输入

          while(in!=13){//如果读到不是13,即回车字符

              in=ins.read();

              System.out.println("读到的一个是: "+in);

          }

          System.out.println("客户机按了回车,退出:"+in);

          client.close();//半闭与这个客户机的连接

    }

       }catch(Exception ef){ef.printStackTrace();}

    }

 

   运行如上程序,在命令行通过telnet连接后,输入一些字符,如图1.13所示。

 

可以看到,在telnet输入界面中,每输入一个字符(串),马上会被发送给服务器。在以上代码示例中,我们还改进了让服务能循环等待客户机连接的功能。

3.读取字符串实现

    要让服务器能读取客户机发来的一段字符串,必须设定一个基本规则:客户机可以连续输入字符给服务器,服务器循环读取,如果收到的字符串有一个回车符,则认为是一条字符串——一条消息。如果收到的字符串是“bye”,则认为客户机要结束通信,就断开客户机。

  实现代码如下:

 

/**

 * 简单Echo服务器实现

 * @author  www.NetJava.cn

 */

public class ChatServer {

    /**

     * 在指定端口上启动一个服务器

     * @param port:服务器所以的端口

     */

    public void setUpServer(int port){

       try{

    //建立绑定在指定端口上的服务器对象

    java.net.ServerSocket server=new java.net.ServerSocket(port);

    System.out.println("服务器创建成功!"+port);

      //当有客户机连接上时,等待方法就会返回,返回一个代表与客户机连接的对象

        while(true){ //让服务器进入循环等待状态

          java.net.Socket client=server.accept();

      System.out.println("Incoming clieng: "+client.getRemoteSocketAddress());

             //调用处理连接对象的方法去处理连接对象

               processChat(client);

            }

       }catch(Exception ef){

           ef.printStackTrace();

       }

    }

    /**

     * 处理连接对象:读取客户机发来的字符串,回送给客户机

     * @param client:与客户机的连接对象

     */

    private void processChat(java.net.Socket client)

    throws Exception{

            OutputStream out=client.getOutputStream();

             InputStream ins=client.getInputStream();

             String s="你好,欢迎来到服务器!\r\n";

              byte[] data=s.getBytes();//取得组成这个字符串的字节

               out.write(data); //用输出对象发送!

                 out.flush();//强制输出

       //调用读取字符串的方法,从输入流中读取一个字符串

                 String inputS=readString(ins);

            while(!inputS.equals("bye")){

                 System.out.println("客户机说: "+inputS);

                  s="服务器收到:"+inputS+"\r\n";

                  data=s.getBytes();//取得组成这个字符串的字节数组

                 out.write(data); //用输出流对象发送!

                 out.flush();//强制输出

                 inputS=readString(ins); //读取客户机的下一次输入

                 }

            s="你好,欢迎再来!\r\n";

            data=s.getBytes();

            out.write(data);

            out.flush();

            client.close();//半闭与客户机的连接

    }

   

    /**

     * 从输入流对象中读取字节,拼成一个字符串返加

     * 如果读到一个字节值为13,则认为以前的是一个字符串

     * @param ins:输入流对象

     * @return :从流上(客户机发来的)读到的字符串

     */

    private String readString(InputStream ins)

     throws Exception{

       //创建一个字符串缓冲区

          StringBuffer stb=new StringBuffer();

         char c =0;

          while(c!=13){

          //遇到一个换行,就是一句话

          int i= ins.read();//读取客户机发来的一个字节

          c=(char)i;//将输入的字节转换为一个Char

          stb.append(c);//将读到的一个字符加到字符串缓冲区中

          }

         //将读到的字节组转为字符串,并调用trim去掉尾部的空格

        String inputS=stb.toString().trim();

       return inputS;

    }

     //程序入口

    public static void main(String[] args) {

       ChatServer cs=new ChatServer();

       cs.setUpServer(9090);

    }

}

  运行如上程序,现在,服务器可以和客户机对话了吗?如图1.14所示。

 
 

4.网络数据传送总结。

    在程序中,字符串最终被以“字节”为单位通过网络发送(接收),再根据双方约定的协议 (如本例中,以回车为一条消息的结束)在程序中进行解析。这个过程如图1.15所示。

 

 

1.15通信时,数据在网络上传送格式的分层示意图

 

  但还有许多问题没有介绍清楚:这些字节是如何被发送到对方IP所在的电脑上的?如果中途丢了字节怎么办?这些字节又是如何转化为为电流信息的……建议大家在完成本节练习后,找一本TCP/IP分析方面的书做深入研读。

    在以上代码的基础上,你可以添加上当客户端连接上服务器后,服务项器提示用户输入用户名、输入密码的功能,然后实现服务器与客户机的聊天功能。

 

    现在最大的缺陷是:这个服务器同时只能与一个客户端通信,测试效果如图1.16所示。

 

 

   当用两个telnet客户端同时连接服务器时,只有一个可以通信,前一个退出后,后一个才能通信。这就是我们下一步的任务:多线程服务器实现。

 

  • 大小: 8.9 KB
  • 大小: 63 KB
  • 大小: 32.5 KB
  • 大小: 60.4 KB
6
0
分享到:
评论
4 楼 zone8089653 2011-07-17  
牛叉
3 楼 rockethj8 2010-10-11  
请问,下一篇文章在哪里呢?没找着~!
2 楼 xici_magic 2010-05-22  
哥们 继续写下去吧 很不错的
1 楼 zhouzhichu 2010-03-08  
不错,简单明了

相关推荐

    Gykg.FlowApp.rar_服务器+客户端_服务器数据库_服务器端 数据库_读写服务器

    winform程序实现BS管理,所有数据库访问在服务器端实现,客户端可以直接读写数据库,但客户没有任何服务器数据库访问痕迹,安全快捷。

    MySQLDBA运维笔记.pdf

    1.4.0 服务器禁止设置外网 IP ......................................................................................21 1.4.1 防 SQL 注入(WEB), php.ini 配置文件里面设置 ..................................

    用Socket编程实现FTP

    它的原理也相当的简单,客户端程序实现一个命令行或图形界面,将用户命令翻译成 FTP 命令,并发送给服务器端程序。服务器端程序响应 FTP 命令,并将操作成功与否的信息以 FTP 响应形式返回给客户端程序。双方遵守 ...

    JAVA_API1.6文档(中文)

    javax.sql 为通过 JavaTM 编程语言进行服务器端数据源访问和处理提供 API。 javax.sql.rowset JDBC RowSet 实现的标准接口和基类。 javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据...

    完全掌握加密解密实战超级手册.zip02

    常见问题解答 247第9章 网络验证技术大放送 2489.1 实现Web服务器网络验证 2499.1.1 加密客户端 2499.1.2 控制本地计算机 2529.2 实现本地服务器验证 2569.2.1 加密客户端 2579.2.2 加密服务器端 2599.3 在线升级...

    基于Go语言的消息推送平台的设计与实现.pdf

    该平台由服务器端与移动端两部份组成,服务端由Go 语言实现,管理后台采用beego 框架与Angularjs 实现前后端分离,底层的连接,数据读写由go 协程和TCP 协议实现。移动端基于Android 平台,采用自定义的协议来建立与...

    linux网路编程 中文 23M 版

    第3 章文件系统简介........................................................ 61 3.1 Linux下的文件系统.................................................. 61 3.1.1 Linux下文件的内涵...........................

    完全掌握加密解密实战超级手册.z01

    常见问题解答 247第9章 网络验证技术大放送 2489.1 实现Web服务器网络验证 2499.1.1 加密客户端 2499.1.2 控制本地计算机 2529.2 实现本地服务器验证 2569.2.1 加密客户端 2579.2.2 加密服务器端 2599.3 在线升级...

    RESTful Web Services 中文版.rar

    第7章:一个服务实现......................167 一个社会性书签Web服务....................167 规划数据集...............................168 资源设计.................................171 设计来自客户端的...

    二十一道面试程序.txt

    1. 写出JDBC的连接(oracle,sql2000,mysql)。...19.用socket通讯写出客户端和服务器端的通讯,要求客户发送数据后能够回显相同的数据? 20.写出jsp的分页。 21.用hibernate的分页技术写出分页代码

    GZU+CS学院+Linux期末题目+题目分析和代码

    5.Linux平台下利用系统接口函数实现Socket客户端服务器端通信程序; 6.在Linux平台下实现不同进程间通信方式的通信演示程序,分析不同通信方式之间的异同; 7.编写线程池控制器,用来对线程池进行控制管理,包括任务...

    [Java参考文档].JDK_API 1.6

    javax.sql 为通过 JavaTM 编程语言进行服务器端数据源访问和处理提供 API。 javax.sql.rowset JDBC RowSet 实现的标准接口和基类。 javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据类型...

    java api最新7.0

    javax.sql 为通过 JavaTM 编程语言进行服务器端数据源访问和处理提供 API。 javax.sql.rowset JDBC RowSet 实现的标准接口和基类。 javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据类型...

    ASP200问.EXE

    69.如何在客户端向服务器端数据库批量添加数据 73.如何对欲删除的记录确认后再删除 74.如何用in关键字实现数据的批量删除 75.如何只读取数据库的前几条记录且如何实现排行榜 76.如何实现在多个表中查询数据 77.如何...

    [Java参考文档]

    javax.sql 为通过 JavaTM 编程语言进行服务器端数据源访问和处理提供 API。 javax.sql.rowset JDBC RowSet 实现的标准接口和基类。 javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据...

    JavaAPI中文chm文档 part2

    javax.sql 为通过 JavaTM 编程语言进行服务器端数据源访问和处理提供 API。 javax.sql.rowset JDBC RowSet 实现的标准接口和基类。 javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据...

    JAVA文件传输的实现.rar

    文件上传:客户端将本地文件传输到服务器端,实现文件的备份、共享或存储。 文件下载:客户端从服务器端获取文件,实现文件的获取和同步。 断点续传:支持在文件传输过程中断,重新连接后能够从断点处继续传输,提高...

    公司网络通信系统源码+毕业论文

    聊天系统主要关注两个方面,即服务器端和客户端。下面分析这两个方面所要完成的任务如下。 1.服务器端的任务: 服务器端应当建立一个Server Socket,并且不断进行侦听是否有客户端连接或者断开连接。服务器端应当是...

Global site tag (gtag.js) - Google Analytics