摘录自http://lbdf001.javaeye.com/blog/548003
socket通信是通过ObjectOutputStream和ObjectInputStream来进行写、读操作的。 首先看一下对象序列化写入,下例将一简单对象序列化到文本文件中:
public class TestSocket {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("c:\\test.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
MyObject myObj = new MyObject();
myObj.setStr1("test1");
myObj.setStr2("test2");
for (int i = 0; i < 1; i++) {
oos.writeObject(myObj);
}
oos.close();
}
}
class MyObject implements Serializable {
private static final long serialVersionUID = 1620871590853110557L;
private String str1;
private String str2;
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
}
当写入一个对象时,文本文件内容如下:
sr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test1t test2
当写入10个相同对象时,文本文件内容如下:
sr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test1t test2q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~
修改代码,写入10个属性值相同的新对象,
for (int i = 0; i < 10; i++) {
MyObject myObj = new MyObject();
myObj.setStr1("test1");
myObj.setStr2("test2");
oos.writeObject(myObj);
}
文本文件内容如下:
sr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test1t test2sq ~ q ~ q ~ sq ~ q ~ q ~ sq ~ q ~ q ~ sq ~ q ~ q ~
sq ~ q ~ q ~ sq ~ q ~ q ~ sq ~ q ~ q ~ sq ~ q ~ q ~ sq ~ q ~ q ~
修改代码,写入10个新对象,且属性值不同
for (int i = 0; i < 10; i++) {
MyObject myObj = new MyObject();
myObj.setStr1("test1" + i);
myObj.setStr2("test2" + i);
oos.writeObject(myObj);
}
文本文件内容如下:
sr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test10t test20sq ~ t test11t test21sq ~ t test12t test22sq ~ t
test13t test23sq ~ t test14t test24sq ~ t test15t test25sq ~ t test16t test26sq ~ t test17t test27sq ~ t test18t test28sq ~ t test19t
test29
通过对比,不是每次都会写入对象的完整信息,而只是在第一次写入了类名、字段名、字段类型等,以后就不会再写入了。这实际是java做的优化,通过该优化从而减少socket传输的开销,要达到这个目的,ObjectOutputStream须持有以前发送对象的引用。如果采用socket长连接的方式,jvm在进行垃圾回收的时候不能回收之前发送的对象的实例,经过漫长时间的运行,最终就会导致内存溢出。
那如何避免该问题呢,ObjectOutputStream有一reset方法,JDK文档中是这么解释该方法的:
“重置将丢弃已写入流中的所有对象的状态。重新设置状态,使其与新的 ObjectOutputStream 相同。将流中的当前点标记为 reset,相应的 ObjectInputStream 也将在这一点重置。以前写入流中的对象不再被视为正位于流中。它们会再次被写入流。”
就是说调用reset释放掉了对象的引用。
修改代码,在每次写入后都调用一下reset()
for (int i = 0; i < 10; i++) {
MyObject myObj = new MyObject();
myObj.setStr1("test1" + i);
myObj.setStr2("test2" + i);
oos.writeObject(myObj);
oos.reset();
}
我们再来看一下写入文件内容:
sr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test10t test20ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test11t test21ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test12t test22ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test13t test23ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test14t test24ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test15t test25ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test16t test26ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test17t test27ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test18t test28ysr org.sunjc.MyObject~~荝k L str1t Ljava/lang/String;L str2q ~ xpt test19t test29ysr
这次跟之前不同,每一次都写入了对象的完整信息。
通过上面一系列的测试,在不调用reset的方式时,java的优化对于减轻socket开销是很可观的,当然是有代价的,那就是直到你调用reset 或者是关闭输出流之前,对于发送过的对象的实例是不会释放的。
结论:当然只是我自己的片面之词。如果你的程序要长时间运行,建议调用reset避免最后内存溢出程序崩溃,但是如果你又要长时间运行,发送的消息量又很大,那么调用reset无疑会增加开销,那么这个时候最好的做法是自己实现一套机制,定时或者是定量(比如查看到内存已经涨到一个水平)的调用reset,这样既可以避免内存无限的增长下去,又可以减少socket通信的开销。
相关推荐
9. **资源管理**:在长连接中,需要妥善管理Socket对象和相关资源,避免内存泄漏和资源耗尽。 10. **异常恢复**:设计合理的重连策略,当连接意外断开时,客户端能够自动尝试重新连接。 在提供的压缩包文件中,...
基于socket的长连接是指两个进程之间建立一次连接后,长时间保持连接状态,而非每次交互都创建新的连接。这样可以减少连接建立和释放的开销,提高整体性能。 在IPLB中使用基于socket的长连接,通常涉及以下关键知识...
- **资源释放**:当不再需要连接时,应及时关闭并释放资源,避免内存泄漏。 - **异常处理**:对于可能出现的各种网络异常,如连接中断、数据传输错误等,应有完善的异常处理机制。 总结起来,`Android-MinaSocket`...
当遇到“librtmp长时间直播socket连接断开”的问题时,可能的原因包括: 1. **网络不稳定**:长时间的直播对网络连接质量有较高要求。网络波动、信号强度下降或者路由器、交换机等硬件设备故障都可能导致连接中断。...
同时,为了防止内存泄漏,需要正确管理和关闭Socket及相关的输入/输出流。 总的来说,Android中的Socket通信结合心跳检测,可以有效地维护长连接的稳定,提高应用程序的用户体验。开发者需要理解Socket通信的基本...
通过安装kb2553549和kb2577795补丁,Windows Server 2008 R2用户可以增强其系统的网络性能,防止由于socket连接管理不当或内存泄漏导致的故障。对于任何运行此类操作系统的IT管理员来说,及时安装这些补丁是维护系统...
每个Socket连接都会在一个独立的线程中处理,以便同时处理多个客户端的请求。服务器端创建新线程来处理每个客户端的连接,客户端也可以在一个单独的线程中读写数据,避免阻塞主线程。 标签中的“p2p”(peer-to-...
2. **生命周期管理**:确保在适当的时候关闭Socket和流,以防止内存泄漏和资源浪费。例如,在Activity的onPause()或onDestroy()方法中。 3. **异步处理**:由于网络操作可能阻塞主线程,建议使用AsyncTask或Handler/...
7. **资源释放**:当不再需要网络连接时,必须使用`关闭套接字`函数释放资源,防止内存泄漏。 由于具体代码并未给出,以上分析基于一般的Socket编程逻辑。如果你有"content.txt"文件的具体内容,可以进一步分析和...
7. **资源释放**:当确认连接断开后,需要正确关闭Socket,释放相关资源,防止内存泄漏。 8. **性能优化**:心跳机制的设计需要考虑性能和效率,例如使用异步IO、非阻塞模式等提高处理速度,减少系统资源消耗。 9....
#### 内存泄漏的原因及示例 内存泄漏通常由以下几种情况引起: 1. **忘记释放内存**:这是最常见的情况,程序员在使用完动态分配的内存后,忘记调用`free()`、`delete`等函数释放内存,如代码片段所示: ```cpp ...
接着,客户端通过Socket连接到服务器,建立连接后,可以使用I/O处理器进行数据的读写。 在服务器端,Mina提供了一个IoHandler接口,开发者需要实现其中的`messageReceived()`方法来处理接收到的客户端消息,以及`...
为了防止内存泄漏,记得在不再使用Socket时调用`Dispose()`方法。 通过学习以上内容,你可以开始构建自己的C# Socket应用程序,无论是简单的聊天应用还是复杂的网络服务。实践是掌握知识的最佳方式,所以尝试编写一...
在完成Socket通信后,务必关闭输入流、输出流以及Socket本身,以防止内存泄漏和资源浪费。 10. **安全性**: 对于敏感数据传输,应使用SSL/TLS加密的Socket(即SSLSocket)以保证通信安全。 综上所述,Android ...
#### 内存泄漏的定义与常见原因 内存泄漏在C/C++编程中是一个常见的问题,尤其是在管理动态分配的内存时。所谓内存泄漏,通常指的是堆内存的泄漏。堆内存是程序运行过程中动态分配的一种内存类型,其大小可以在运行...
`close()`函数可以释放Socket资源,避免内存泄漏。 总结起来,C语言中的Socket编程涉及了网络通信的基础知识,包括Socket的创建、连接、监听,以及自定义协议的设计和实现。通过熟练掌握这些技术,开发者可以构建...
3. 稳定性测试:长时间运行压力测试,检查系统是否会出现内存泄漏、性能下降等问题。 4. 错误恢复测试:模拟网络异常情况,如断线重连,检验系统的恢复能力和错误处理机制。 四、HP-Socket压力测试工具 HP-Socket...
在程序关闭时,记得释放Socket资源,防止内存泄漏。在C#中,这通常通过重写`Dispose`方法来实现,如示例中所示,关闭Socket并中止处理线程。 总的来说,C#中的Socket编程涉及服务端和客户端的交互,包括创建Socket...
当通信完成后,记得关闭Socket和相关的资源,如NetworkStream,以防止内存泄漏和资源浪费。 9. **套接字选项与属性** Socket类还有许多属性和方法,如NoDelay(禁用Nagle算法)、KeepAlive(心跳检测)等,可以...
4. **关闭连接**:通信完成后,客户端和服务器都需要关闭Socket连接,释放资源,防止内存泄漏。 在"压缩包子文件的文件名称列表"中,"C#+Socket异步传输"可能包含了服务端和客户端的源码文件。这些文件通常包括了...