`
dpzc
  • 浏览: 13059 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

java网络编程 使用长连接

    博客分类:
  • java
阅读更多
    最近涉及了一些网络编程,在这里总结一下。
    项目是一个多域仿真系统,模型简要说明下:局域网中有l台机器,代表l个域,每个域有n个节点,每个节点有m种资源每次仿真时,随机选一个节点申请某个资源,这个资源可能好几个域上都有节点拥有它。选择信誉值最高的节点作为服务者,与其进行交互。
    对网络的要求是,可以将一个域上的东西发到另一个节点。最开始的想法是tcp开销较大且局域网丢包概率很小,因此考虑用简单快捷的UDP进行传输。UDP协议是无连接的协议,在JAVA中java.util.DatagramSocket负责接收和发送UDP数据报,Datagrampacket表示UDP数据报。DatagramSocket提供了接收和发送数据报的方法。
public void receive(DatagramPacket dst)throws IOException
public void send(DatagramPacket p)throws IOException

测试时发现会报异常,UDP规定每个包大小不能超过64K,而我们传送的数据至少几百KB。期间考虑过手工编号分组的方法,但没能成功。转而考虑TCP。
    TCP中服务器程序监听端口,接收客户程序的连接请求。
ServerSocket server=new ServerSocket(8000);

用accpet()方法等待客户连接请求,这个方法是阻塞的,直到有客户连接才返回一个Socket对象
Socket socket=server.accept();

客户端用
Socket socket=new Socket(addr,port);
建立和server的连接。
    项目采用TCP连接后可以正常传输数据了,但是由于仿真一次所需时间只要一、两秒钟时间,频繁创建socket导致程序不稳定。后经导师提醒,采用长连接的方法,即一个域初始化时,就与局域网中其他所有域建立tcp连接,这个连接建立后不关闭,因为每次仿真几乎都要传输数据。修改时碰到第一个问题是,以前accept方法是阻塞的,即需要发数据时客户端建立socket,服务端监听线程就收到一个请求,交与处理线程处理。现在socket保持连接,如何知道客户端要发送数据了呢?
    直接说解决方法了。长连接是要把socket保存下来的,新建socket的同时,取得它的输出流,因为要发送对象,用ObjectOutputStream来装饰。
sendObjectStream = new ObjectOutputStream(sendSocket.getOutputStream());

要发送时,只要得到sendObjectStream ,调用writeObject即可。由于每个节点即可能是客户端也可能是服务端,每个域可能同时进行发送和接收,这时可以使用保存的这个socket接收,我是在新建这个socket时,就开一个接收线程,把这个socket传过去用于接收。
public class Receiver implements Runnable{
 private Socket s = null;
 private ObjectInputStream ois = null;
 private static volatile boolean bConnected = false;
 private Network network;
 
 public Receiver(Socket s,Network n){
 	this.s = s;
 	this.network = n;
 	bConnected = true;
		try {
			ois = new ObjectInputStream(s.getInputStream());
		} catch (IOException e) {
			System.out.println("S关闭了");
			e.printStackTrace();
		}
 }

	public void run()
	{
		try
		{
			while(bConnected)
			{
				try
				{
					long begin = System.currentTimeMillis();
					NetParameterPacket  npp = (NetParameterPacket) ois.readObject();
					long end = System.currentTimeMillis();
					System.out.println("readObject用的时间为"+(end-begin)+"ms");
					PacketHandle ph = new PacketHandle(npp,network,s);
					new Thread(ph).start();
				}
				catch(EOFException e)
				{
					System.out.println("此时无数据");
					try
					{
						Thread.sleep(500);
					} catch (InterruptedException e1)
					{
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
				catch (IOException e)
				{
					e.printStackTrace();
					if(e instanceof SocketException)
					{
						bConnected=false;
					}
				} catch (ClassNotFoundException e)
				{
					e.printStackTrace();
				}
			}
		} 
		finally
		{
			if(ois!=null){
				try
				{
					ois.close();
				} catch (IOException e)
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				ois = null;
			}
			if(s!= null){
				try {
					s.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				s = null;
			}
		}		
	}

	public static void setBConnected(boolean connected)
	{
		bConnected = connected;
	}
}


关于谁向谁新建TCP的问题:局域网中A域在运行时,这时B域申请加入。B域首先在局域网中广播,A域收到广播后进行响应,new一个socket向其建立tcp连接,并新建接收线程,将这个socket传过去用于接收。B域监听到这个tcp后,得到socket=server.accpet();新开一个接收线程的同时,将这个socket保存下来用于发送TCP。发送TCP代码为
public void sendTCPSingle(Object o , String address)
	{
		Domain d = getDomainByName(address);
		if(d == null)
		{
			System.out.println("没找到该domain");
			return;
		}
		try
		{
			sendLock.lock();
			ObjectOutputStream oos = d.getSendObjectStream();		
			oos.writeObject(o);
			oos.flush();	
		} catch (IOException e)
		{
			System.out.println("发送对象出错!");			
			
			//对发送异常进行处理			
			SocketAddress remoteAddr = new InetSocketAddress(address,TCP_PORT);
			try
			{
				if(d.getSendSocket().isClosed())
				{
					Socket newSocket = new Socket(address,TCP_PORT);
					System.out.println("socket已经关闭,重新向"+address+"发送建立TCP连接请求");
					d.setSendSocket(newSocket);
				}
				else
					d.getSendSocket().connect(remoteAddr);
			} 
			catch (IOException e1)
			{
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		finally
		{
			sendLock.unlock();
		}
	}

其中Domain类表示域。

用加锁的原因是,某次交互可能两个线程同时准备发送,这时发送的一方会报异常java.net.SocketException: Software caused connection abort: socket write error,接收方也跟着异常java.io.StreamCorruptedException: invalid type code: 00

网上说长连接要用心跳方法检测对方是否还活着,这里因为是局域网且数据一直要传送,就没使用。
分享到:
评论
5 楼 twocat 2009-12-11  
dpzc 写道
twocat 写道
dpzc兄,你好油菜啊,稀饭~~~

twocat姐,晚上有空吗,出来喝茶

对你什么时候都有空。。晚上教我怎么使用长链接哈
4 楼 dpzc 2009-12-10  
twocat 写道
dpzc兄,你好油菜啊,稀饭~~~

twocat姐,晚上有空吗,出来喝茶
3 楼 twocat 2009-12-10  
dpzc兄,你好油菜啊,稀饭~~~
2 楼 dpzc 2009-12-08  
twocat 写道
哈哈,来支持一下

twocat姐,你好啊
1 楼 twocat 2009-12-01  
哈哈,来支持一下

相关推荐

    Java网络编程案例教程习题参考答案 .pdf

    6. 网络编程常见问题:Java网络编程中常见的问题包括网络连接问题、数据传输问题、网络安全问题等。Java程序员需要了解这些问题的解决方法和对策。 7. Java网络编程中的多线程:Java网络编程中多线程编程是指使用多...

    Java网络编程/Java网络编程实例

    Java网络编程是Java开发中的重要领域,它涵盖了网络应用程序的设计、实现和调试。在这个主题下,我们可以探讨多个关键知识点: 1. **Java Socket编程**:Java的Socket类提供了基于TCP/IP协议的网络通信能力。通过...

    Java网络编程实验报告.pdf

    "Java网络编程实验报告" 本实验报告主要介绍了Java网络编程的基本概念和实现方法,通过设计和实现一个简单的客户端/服务器应用程序,了解Java网络编程的基本原理和实现方法。 知识点1:Java 网络编程基础 Java ...

    Java网络编程(第4版)PDF

    《Java网络编程(第4版)》是一本深入探讨Java平台上的网络编程技术的专业书籍,适合想要提升Java通讯技术的学者阅读。此书全面覆盖了Java网络编程的基础和高级概念,帮助开发者理解如何利用Java语言构建高效、可靠的...

    java网络编程第四版pdf

    《Java网络编程(第四版)》是一本深入探讨Java在互联网环境下的编程技术的经典书籍。本书旨在帮助读者理解和掌握如何利用Java语言进行高效、安全的网络通信。书中内容覆盖了从基本的网络概念到复杂的多线程编程,是...

    Java网络编程期末考试复习题库+答案

    Java网络编程是计算机科学中的一个重要领域,特别是在软件开发中,它涉及到如何通过网络进行数据传输和通信。在Java中,网络编程主要依赖于Java的Socket编程、ServerSocket、URL类以及NIO(非阻塞I/O)等核心API。这...

    java网络编程

    在本资料中,《Java网络编程》第三版提供了深入浅出的讲解,旨在帮助开发者提升对这一领域的理解。 1. **基础概念**: - **网络模型**:Java网络编程基于OSI七层模型和TCP/IP四层模型。理解这些模型有助于理解网络...

    Java网络编程-多线程,连接池

    Java网络编程是构建分布式应用程序的关键技术,特别是在服务器端开发中,多线程和连接池是其核心概念。本文将深入探讨这两个主题,并结合文件传输的实际应用进行讲解。 首先,我们来理解多线程。在Java中,多线程...

    《Java网络编程实例:Java网络编程实例》

    Java网络编程是开发分布式应用程序的关键技术,它使得Java程序能够与其他设备、系统和服务进行通信。本书《Java网络编程实例:Java网络编程实例》显然聚焦于通过实际案例来教授这一核心技能。以下是一些主要的知识点...

    java网络编程使用的简单例子

    Java网络编程是开发...这个"java网络编程使用的简单例子"可能包含了以上提到的一些概念,通过实际的代码示例,可以帮助我们更好地理解和应用这些知识。学习和实践这些内容,将有助于开发高效、可靠的网络应用程序。

    Java网络编程第三版.pdf

    1. **Java网络编程基础**:首先,书中会介绍Java中的Socket编程,包括TCP和UDP协议的基础知识,以及如何使用Java的Socket和ServerSocket类创建客户端和服务器端的连接。 2. **I/O与NIO**:Java的I/O流系统是网络...

    Java网络编程实例(随书源代码)

    Java网络编程是开发分布式应用程序的关键技术,它允许程序通过网络发送和接收数据。《Java网络编程实例》这本书的源代码提供了丰富的示例,帮助读者深入理解这一领域。本压缩包包含的源代码覆盖了Java网络编程的各种...

    Java网络编程精解(孙卫琴)电子教案

    《Java网络编程精解》是孙卫琴老师的一本经典教程,主要涵盖了Java语言在网络编程领域的深度解析。这本书深入浅出地介绍了如何使用Java进行网络通信,包括基本的TCP/IP协议、套接字编程、多线程技术以及HTTP、FTP等...

    Java网络编程资料

    Java网络编程是开发分布式应用程序的关键技术,它允许Java程序与其他计算机进行通信,实现数据的交换。这份"Java网络编程资料"包含三个重要的学习资源:关于Socket套接字的"Java套接字编程.chm"、关于网络协议特别是...

    JAVA网络编程大全,pdf版

    《JAVA网络编程大全》是一本全面且深入介绍Java网络编程技术的权威著作,旨在帮助读者掌握Java在构建网络应用程序中的核心概念和实践技巧。PDF版的书籍为学习者提供了便捷的电子阅读体验,随时随地都能深化对Java...

    java网络编程源码

    Java网络编程是Java开发中的重要领域,它涵盖了网络通信的所有基本概念和技术,包括TCP/IP协议栈、套接字(Socket)编程、多线程、数据传输格式等。孙卫琴的《java网络编程》一书深入浅出地讲解了这些核心概念,并...

    Java网络编程.chm

    本资源为"Java网络编程.chm",是一本关于Java网络编程的电子书,以实例驱动的方式深入讲解了相关知识。 首先,我们要理解Java在网络编程中的基础——IO流。Java中的IO流分为字节流和字符流,它们用于读写数据,包括...

    java网络编程经典的学习书籍

    《Java网络编程》是编程领域的经典著作,尤其对于学习Java网络编程的初学者及进阶者来说,这本书具有很高的参考价值。它详细介绍了如何利用Java语言进行网络通信,涵盖了网络编程的基本概念、协议以及实现方法。 一...

    java网络编程课件.zip

    总的来说,"java网络编程课件.zip"是一个全面的教程,可以帮助学习者从基础到进阶掌握Java网络编程的各个方面,包括TCP/IP通信、套接字编程、HTTP协议、多线程以及输入/输出流的使用。通过深入学习和实践,开发者...

    java网络编程 PPT

    2. **Java网络编程API**:深入解析Java的Socket编程,包括ServerSocket和Socket类的使用,以及如何创建基于TCP的套接字连接。同时,也会涉及DatagramSocket和MulticastSocket类,讲解UDP(用户数据报协议)的无连接...

Global site tag (gtag.js) - Google Analytics