陈跃峰的J2ME博客

Java,J2ME技术教师 + 自由撰稿人,承接J2ME手机软件开发

用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
Mailbomb的公告
陈跃峰 <a href="http://blog.csdn.net/mailbomb/posts/296349.aspx" target="_blank">个人简历</a><br> cqucyf@gmail.com <font color=red> <h4> 各计算机杂志需要Java、J2ME技术或手机游戏开发相关稿件的可以联系我,联系方式:cqucyf@gmail.com </h4></font> 本人编写的Java基础入门书籍: 《Java编程那些事儿》,购买<br> <a href="http://product.dangdang.com/product.aspx?product_id=20765518" target="_blank">当当网</a><br> <a href="http://www.china-pub.com/1858633" target="_blank">Chinapub</a><br>
文章分类
J2ME技术
J2ME中国
J2ME开发网
Java网站
Eclipse官方网站
Java世纪网
Sun中国
Sun官方网站
常用网站
Chinabyte
Google搜索引擎
华军软件园
新浪新闻
发表过文章的媒体
IT世界网
电脑报
电脑编程技巧与维护
软件报
网上书店
ITbook
互动出版网
当当书店
第二书店
我工作过的地方
上海东部软件园有限公司
上海天软科技有限公司
上海托普信息技术学院
游戏学院南京校区
游戏学院郑州校区
电脑报
友情链接
acqy的专栏
eiyaa的专栏
JavaMeStudio
刀剑啸的专栏
刘军的BLOG
王新钢的BLOG
老紫竹的专栏
贝壳鱼(k7sem)专栏
骄傲的猫
存档

原创  Java编程那些事儿106——网络编程技术5 收藏

Java编程那些事儿106——网络编程技术5

陈跃峰

出自:http://blog.csdn.net/mailbomb

该示例的功能是实现将客户端程序的系统时间发送给服务器端,服务器端接收到时间以后,向客户端反馈字符串“OK”。实现该功能的客户端代码如下所示:

        package udp;

import java.net.*;

import java.util.*;

/**

 * 简单的UDP客户端,实现向服务器端发生系统时间功能

 */

public class SimpleUDPClient {

            public static void main(String[] args) {

                     DatagramSocket ds = null;  //连接对象

                     DatagramPacket sendDp; //发送数据包对象

                DatagramPacket receiveDp; //接收数据包对象

                     String serverHost = "127.0.0.1"; //服务器IP

                int serverPort = 10010;  //服务器端口号

                     try{

                        //建立连接

                        ds = new DatagramSocket();

                        //初始化发送数据

                        Date d = new Date(); //当前时间

                        String content = d.toString(); //转换为字符串

                        byte[] data = content.getBytes();

                        //初始化发送包对象

                        InetAddress address = InetAddress.getByName(serverHost);

                        sendDp = new DatagramPacket(data,data.length,address,serverPort);

                        //发送

                        ds.send(sendDp);

                                                                          

                        //初始化接收数据

                        byte[] b = new byte[1024];

                        receiveDp = new DatagramPacket(b,b.length);

                        //接收

                        ds.receive(receiveDp);

                        //读取反馈内容,并输出

                        byte[] response = receiveDp.getData();

                        int len = receiveDp.getLength();

                        String s = new String(response,0,len);

                        System.out.println("服务器端反馈为:" + s);

                }catch(Exception e){

                        e.printStackTrace();

                }finally{

                        try{

                           //关闭连接

                           ds.close();

                        }catch(Exception e){}

                }

            }

        }

在该示例代码中,首先建立UDP方式的网络连接,然后获得当前系统时间,这里获得的系统时间是客户端程序运行的本地计算机的时间,然后将时间字符串以及服务器端的IP和端口,构造成发送数据包对象,调用连接对象dssend方法发送出去。在数据发送出去以后,构造接收数据的数据包对象,调用连接对象dsreceive方法接收服务器端的反馈,并输出在控制台。最后在finally语句块中关闭客户端网络连接。

和下面将要介绍的服务器端一起运行时,客户端程序的输出结果为:

    服务器端反馈为:OK

下面是该示例程序的服务器端代码实现:

        package udp;

        import java.net.*;

        /**

         * 简单UDP服务器端,实现功能是输出客户端发送数据,

           并反馈字符串“OK"给客户端

         */

        public class SimpleUDPServer {

            public static void main(String[] args) {

                     DatagramSocket ds = null;  //连接对象

                     DatagramPacket sendDp; //发送数据包对象

                     DatagramPacket receiveDp; //接收数据包对象

                     final int PORT = 10010; //端口

                                               try{

                        //建立连接,监听端口

                        ds = new DatagramSocket(PORT);

                        System.out.println("服务器端已启动:");

                        //初始化接收数据

                        byte[] b = new byte[1024];

                        receiveDp = new DatagramPacket(b,b.length);

                        //接收

                        ds.receive(receiveDp);

                        //读取反馈内容,并输出

                        InetAddress clientIP = receiveDp.getAddress();

                        int clientPort = receiveDp.getPort();

                        byte[] data = receiveDp.getData();

                        int len = receiveDp.getLength();

                        System.out.println("客户端IP" + clientIP.getHostAddress());

                        System.out.println("客户端端口:" + clientPort);

                        System.out.println("客户端发送内容:" + new String(data,0,len));

                                                                          

                        //发送反馈

                        String response = "OK";

                        byte[] bData = response.getBytes();

                        sendDp = new DatagramPacket(bData,bData.length,clientIP,clientPort);

                        //发送

                        ds.send(sendDp);

                                               }catch(Exception e){

                        e.printStackTrace();

                                               }finally{

                        try{

                           //关闭连接

                           ds.close();

                        }catch(Exception e){}

                                               }

            }

        }

在该服务器端实现中,首先监听10010号端口,和TCP方式的网络编程类似,服务器端的receive方法是阻塞方法,如果客户端不发送数据,则程序会在该方法处阻塞。当客户端发送数据到达服务器端时,则接收客户端发送过来的数据,然后将客户端发送的数据内容读取出来,并在服务器端程序中打印客户端的相关信息,从客户端发送过来的数据包中可以读取出客户端的IP以及客户端端口号,将反馈数据字符串“OK”发送给客户端,最后关闭服务器端连接,释放占用的系统资源,完成程序功能示例。

和前面TCP方式中的网络编程类似,这个示例也仅仅是网络编程的功能示例,也存在前面介绍的客户端无法进行多次数据交换,以及服务器端不支持多个客户端的问题,这两个问题也需要对于代码进行处理才可以很方便的进行解决。

在解决该问题以前,需要特别指出的是UDP方式的网络编程由于不建立虚拟的连接,所以在实际使用时和TCP方式存在很多的不同,最大的一个不同就是“无状态”。该特点指每次服务器端都收到信息,但是这些信息和连接无关,换句话说,也就是服务器端只是从信息是无法识别出是谁发送的,这样就要求发送信息时的内容需要多一些,这个在后续的示例中可以看到。

下面是实现客户端多次发送以及服务器端支持多个数据包同时处理的程序结构,实现的原理和TCP方式类似,在客户端将数据的发送和接收放入循环中,而服务器端则将接收到的每个数据包启动一个专门的线程进行处理。实现的代码如下:

    package udp;

    import java.net.*;

    import java.util.*;

    /**

     * 简单的UDP客户端,实现向服务器端发生系统时间功能

     * 该程序发送3次数据到服务器端

     */

    public class MulUDPClient {

                  public static void main(String[] args) {

                 DatagramSocket ds = null;  //连接对象

                                     DatagramPacket sendDp; //发送数据包对象

                                     DatagramPacket receiveDp; //接收数据包对象

                                     String serverHost = "127.0.0.1"; //服务器IP

                                     int serverPort = 10012;  //服务器端口号

                                     try{

                    //建立连接

                    ds = new DatagramSocket();

                    //初始化

                               InetAddress address = InetAddress.getByName(serverHost);

                    byte[] b = new byte[1024];

                    receiveDp = new DatagramPacket(b,b.length);

                    System.out.println("客户端准备完成");

                    //循环30次,每次间隔0.01

                    for(int i = 0;i < 30;i++){

                                                        //初始化发送数据

                                                        Date d = new Date(); //当前时间

                                                        String content = d.toString(); //转换为字符串

                                                        byte[] data = content.getBytes();

                                                        //初始化发送包对象

                                                        sendDp = new DatagramPacket(data,data.length,address, serverPort);

                                                        //发送

                                                        ds.send(sendDp);

                                                        //延迟

                                                        Thread.sleep(10);

                                                        //接收

                                                        ds.receive(receiveDp);

                                                        //读取反馈内容,并输出

                                                        byte[] response = receiveDp.getData();

                                                        int len = receiveDp.getLength();

                                                        String s = new String(response,0,len);

                                                        System.out.println("服务器端反馈为:" + s);

                     }

                 }catch(Exception e){

                     e.printStackTrace();

                 }finally{

                     try{

                                                        //关闭连接

                                                        ds.close();

                     }catch(Exception e){}

                 }

         }

     }

在该示例中,将和服务器端进行数据交换的逻辑写在一个for循环的内部,这样就可以实现和服务器端的多次交换了,考虑到服务器端的响应速度,在每次发送之间加入0.01秒的时间间隔。最后当数据交换完成以后关闭连接,结束程序。

实现该逻辑的服务器端程序代码如下:

package udp;

import java.net.*;

/**

* 可以并发处理数据包的服务器端

* 功能为:显示客户端发送的内容,并向客户端反馈字符串“OK

*/

public class MulUDPServer {

public static void main(String[] args) {

DatagramSocket ds = null;  //连接对象

DatagramPacket receiveDp; //接收数据包对象

final int PORT = 10012; //端口

byte[] b = new byte[1024];

receiveDp = new DatagramPacket(b,b.length);

try{

//建立连接,监听端口

ds = new DatagramSocket(PORT);

System.out.println("服务器端已启动:");

while(true){

//接收

ds.receive(receiveDp);

//启动线程处理数据包

new LogicThread(ds,receiveDp);

}

}catch(Exception e){

         e.printStackTrace();

}finally{

try{

//关闭连接

ds.close();

}catch(Exception e){}

}

}

}

该代码实现了服务器端的接收逻辑,使用一个循环来接收客户端发送过来的数据包,当接收到数据包以后启动一个LogicThread线程处理该数据包。这样服务器端就可以实现同时处理多个数据包了。

实现逻辑处理的线程代码如下:

package udp;

import java.net.*;

/**

 * 逻辑处理线程

 */

public class LogicThread extends Thread {

/**连接对象*/

DatagramSocket ds;

/**接收到的数据包*/

DatagramPacket dp;

 

public LogicThread(DatagramSocket ds,DatagramPacket dp){

this.ds = ds;

this.dp = dp;

start(); //启动线程

}

 

public void run(){

try{

//获得缓冲数组

byte[] data = dp.getData();

//获得有效数据长度

int len = dp.getLength();

//客户端IP

InetAddress clientAddress = dp.getAddress();

//客户端端口

int clientPort = dp.getPort();

//输出

System.out.println("客户端IP" + clientAddress.getHostAddress());

System.out.println("客户端端口号:" + clientPort);

System.out.println("客户端发送内容:" + new String(data,0,len));

//反馈到客户端

byte[] b = "OK".getBytes();

DatagramPacket sendDp = new DatagramPacket(b,b.length,clientAddress,clientPort);

//发送

ds.send(sendDp);

}catch(Exception e){

e.printStackTrace();

}

}

}

在该线程中,只处理一次UDP通讯,当通讯结束以后线程死亡,在线程内部,每次获得客户端发送过来的信息,将获得的信息输出到服务器端程序的控制台,然后向客户端反馈字符串“OK”。

由于UDP数据传输过程中可能存在丢失,所以在运行该程序时可能会出现程序阻塞的情况。如果需要避免该问题,可以将客户端的网络发送部分也修改成线程实现。

关于基础的UDP网络编程就介绍这么多了,下面将介绍一下网络协议的概念。

发表于 @ 2009年06月14日 16:45:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:Java编程那些事儿105——网络编程技术4 | 新一篇:Java编程那些事儿107——网络协议概念

  • 发表评论
  • 评论内容:
  •  
Copyright © Mailbomb
Powered by CSDN Blog