多线程+socket+文件读写(面)
2010年08月17日
多线程+socket+文件读写(面)
文章分类:Java编程 说明:此文档,只是对之前多线程,socket,文件读写三个文档中的基础,关键部分作一次整合。因为socket中会用到多线程,及文件读写,方便整体阅读。
------------------------------------多线程----------------------------------
多线程:
0.
多线程的概念:
多线程是这样一种机制,它允许在程序中并发执行多个线程,且每个线程彼此间互相独立。
并发的理解:
多个线程的执行是并发的,也就是在逻辑上"同时",而不管是否是物理上的"同时"。
1.
实现线程的方式有两种:
1、继承java.lang.Thread,并重写它的run()方法,将线程的执行主体放入其中。
2、实现java.lang.Runnable接口,实现它的run()方法,并将线程的执行主体放入其中。
==>多线程的执行逻辑:
当主线程被挂起时, 其它就绪的线程会根据选择最高优先级的来执行;
当主线程的挂起时间 > 子线程的执行时间时,子线程执行完后回到主线程,等待主线程醒来.
当主线程的挂起时间 返回时才将锁释放;此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态.
也就是说:
线程在执行同步方法时是具有排它性的。当任意一个线程进入到一个对象的任意一个同步方法时,这个对象的所有同步方法都被锁定了,在此期间,其他任何线程都不能访问这个对象的任意一个同步方法,直到这个线程执行完它所调用的同步方法并从中退出,从而导致它释放了该对象的同步锁之后。在一个对象被某个线程锁定之后,其他线程是可以访问这个对象的所有非同步方法的。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
同步块也一样:
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
基本格式:
同步方法:
Java代码
public void methodAAA()
{
synchronized (this) // (1) {
//….. } }
public void methodAAA() { synchronized (this) // (1) { //….. } } 同步块:
Java代码
public void methodAAA()
{
synchronized (this) // (1) {
//….. } }
public void methodAAA() { synchronized (this) // (1) { //….. } } 实例如下:
同步方法:
Java代码
public class Thread1 implements Runnable {
int num=100;
public synchronized void run() {
for (int i = 0; i
public class Thread1 implements Runnable {
int num = 100;
public void run() {
synchronized (this) {
for (int i = 0; i 结果:
A 's num is 100
A 's num is 99
A 's num is 98
A 's num is 97
A 's num is 96
B 's num is 95
B 's num is 94
B 's num is 93
B 's num is 92
B 's num is 91
若不添加同步:
A 's num is 100
A 's num is 98
A 's num is 97
A 's num is 96
A 's num is 95
B 's num is 99 --此处
B 's num is 94
B 's num is 93
B 's num is 92
B 's num is 91
说明:
则线程A正在处理的中间数据若结果数据(99),将线程B中调用了;A又调用了线程B的中间数据,继续计算.
注意:
在定义接口方法时不能使用synchronized关键字。
构造方法不能使用synchronized关键字,但可以使用下节要讨论的synchronized块来进行同步。
3.
Lock是一个接口,它位于Java 5.0新增的java.utils.concurrent包的子包locks中。实现Lock接口的类具有与synchronized关键字同样的功能,但是它更加强大一些。java.utils.concurrent.locks.ReentrantLock是较常用的实现了Lock接口的类。上面的实例可以变为:
Java代码
public class Thread1 implements Runnable {
int num = 100;
private Lock lock = new ReentrantLock();
public void run() {
try {
lock.lock();
for (int i = 0; i 等待这个进程中的其他线程释放所占用的资源,从而导致所有线程都无法继续执行的情况。
4.
线程的阻塞
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),Java 提供了大量方法来支持阻塞,下面让我们逐一分析。
1. sleep() 方法:sleep() 允许指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。
2. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。
3. yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。
4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify () 被调用。
区别:
初看起来 wait() 和 notify()与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而 wait() 和 notify()这一对方法则相反, wait() 方法导致线程阻塞,并且该对象上的锁被释放。
在上面的实例中修改:
Java代码
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
try {
ta.sleep(10000);
}
catch (Exception e) {}
tb.start();
}
public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); try { ta.sleep(10000); } catch (Exception e) {} tb.start(); } 在输出A的5条记录后,须等10秒,才输出B的.
若用wait(),则直接输出A,B信息.
JAVA多线程编程。用JAVA写一个多线程程序,如写四个线程,二个加1,二个对一个变量减一,输出。(须考虑同步)
Java代码
//将要加减的变量设置为static;将加减操作及相应的变量定义在另一类中.在线程中进行调用即可.
//只要是多线程,就要考虑其同步.即要用synchrnized
class t {
private static int x=10;
public synchronized void add()
{
x++;
System.out.println("x="+x);
}
public synchronized void jian()
{
x--;
System.out.println("x="+x); }
}
class t1 extends Thread
{
public void run()
{
t t1=new t();
t1.add();
}
}
class t2 extends Thread
{
public void run()
{
t t1=new t();
t1.jian();
} }
public class ThreadTest
{
public static void main(String [] args)
{
t1 t11=new t1();
t1 t12=new t1();
t2 t21=new t2();
t2 t22=new t2();
t11.start();
t12.start();
t21.start();
t22.start();
} }
//将要加减的变量设置为static;将加减操作及相应的变量定义在另一类中.在线程中进行调用即可. //只要是多线程,就要考虑其同步.即要用synchrnized class t { private static int x=10; public synchronized void add() { x++; System.out.println("x="+x); } public synchronized void jian() { x--; System.out.println("x="+x); } } class t1 extends Thread { public void run() { t t1=new t(); t1.add(); } } class t2 extends Thread { public void run() { t t1=new t(); t1.jian(); } } public class ThreadTest { public static void main(String [] args) { t1 t11=new t1(); t1 t12=new t1(); t2 t21=new t2(); t2 t22=new t2(); t11.start(); t12.start(); t21.start(); t22.start(); } } 5.
线程池
线程池就像数据库连接池一样,是一个对象池。所有的对象池都有一个共同的目的,那就是为了提高对象的使用率,从而达到提高程序效率的目的.
多线程---守护线程
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
Daemon的作用是为其他线程的运行提供便利服务,比如垃圾回收线程就是一个很称职的守护者。
6.
终止线程三种方式:
当run方法完成后线程终止;
使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果);
使用interrupt方法中断线程.
------------------------------------文件读写----------------------------------
I/O操作
对于输入/输出问题,Java将之抽象化为流(Stream)对象来解决。
对输入/输出流,及文件的处理,注意要在最后关闭流或文件,且在处理前后添加try..catch.
Reader、Writer与其子类可以用于进行所谓纯文本文件的字符读/写.
InputStreamReader和OutputStreamWriter (它们分别为Reader和Writer的子类.)
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
int ch = 0;
// 以字符方式显示文件内容
while ((ch = inputStreamReader.read()) != -1) {
outputStreamWriter.write(ch);
}
inputStreamReader.close();
outputStreamWriter.close();
FileReader和FileWriter(它们分别继承自InputStreamReader与 OutputStreamWriter)
操作更加简单,不用先建input/outputstream,直接将路径放上去就行.
FileReader fileReader = new FileReader("D:\\jason.txt");
FileWriter fileWriter = new FileWriter("D:\\change.txt");
BufferedReader和BufferedWriter(常用于整行读写,单字读写用上面的两类)
读写效率比较高,但须先创建InputStreamReader/OutputStreamWriter或FileReader/FileWriter作为其参数
try {
BufferedReader reader=new BufferedReader(new FileReader("D:\\jason.log"));
BufferedWriter writer=new BufferedWriter(new FileWriter("D:\\change.txt"));
String show=reader.readLine(); //读取第一行信息
while(!show.equals("bye"))
{
System.out.println(show);
writer.write(show+"\n"); //其中\n用于换行
show=reader.readLine(); //进行循环读取
}
writer.flush();
reader.close();
writer.close();
} catch (Exception ee) {
ee.printStackTrace();
}
注意:只有BufferedReader或BufferedInputStream,没有BufferedInputStreamReader.
说明:
BufferedReader的readline()方法,实际就是以下的样式的定制:
byte[] a=new byte[2]; --->自己定制缓存的大小,而readline(),则是原先定制好的.
.....
if((ch=A.read(a))!=-1)
{B.wirte(a)}
------------------------------------socket-------- --------------------------
socket,
对输入/输出流,及文件的处理,注意要在最后关闭流或文件,且在处理前后添加try..catch
我们可以做一个简单的 Socket 例程了 .
服务端 :
Java代码
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break; }
client.close();
} }
import java.io.*; import java.net.*; public class MyServer { public static void main(String[] args) throws IOException{ ServerSocket server=new ServerSocket(5678); Socket client=server.accept(); BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter out=new PrintWriter(client.getOutputStream()); while(true){ String str=in.readLine(); System.out.println(str); out.println("has receive...."); out.flush(); if(str.equals("end")) break; } client.close(); } }
注意:只有BufferedReader或BufferedInputStream,没有BufferedInputStreamReader.
这个程序的主要目的在于服务器不断接收客户机所写入的信息直到客户机发送 "End" 字符串就退出程序 . 并且服务器也会做出 "Receive" 为回应 . 告知客户机已接收到消息 .
客户机代码 :
Java代码
import java.net.*;
import java.io.*;
public class Client{
static Socket server;
public static void main(String[] args)throws Exception{
server=new Socket(InetAddress.getLocalHost(),5678);
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));
while(true){
String str=wt.readLine();
out.println(str);
out.flush();
if(str.equals("end")){
break;
}
System.out.println(in.readLine());
}
server.close();
} }
import java.net.*; import java.io.*; public class Client{ static Socket server; public static void main(String[] args)throws Exception{ server=new Socket(InetAddress.getLocalHost(),5678); BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream())); PrintWriter out=new PrintWriter(server.getOutputStream()); BufferedReader wt=new BufferedReader(new InputStreamReader(System.in)); while(true){ String str=wt.readLine(); out.println(str); out.flush(); if(str.equals("end")){ break; } System.out.println(in.readLine()); } server.close(); } }
这个程序只是简单的两台计算机之间的通讯 . 如果是多个客户同时访问一个服务器呢 ? 你可以试着再运行一个客户端 , 结果是会抛出异常的 . 那么多个客户端如何实现呢 ?
如何实现多线程并发socket通讯:
服务端socket,负责监听socket端口,设置一个无限循环,在其中实现:将监听到的socket实例赋给线程且启动线程,由线程来完成业务逻辑.具体如下:
import java.net.*;
import java.io.*;
public class MultiUser extends Thread{
private Socket client;
public MultiUser(Socket c){
this.client=c;
}
public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
//Mutil User but can't parallel
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}catch(IOException ex){
}finally{
}
}
myserver.java修改如下:
public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(server.accept());
mu.start();
}
}
}
2.
用socket传输文件,实际就是打开文件,将内容读取发送到对方,对方获取保存到文件中。
用socket可以传输对象--ObjectInputStream/ObjectOutputStream
1. 对于普通的传输字符串,用 BufferedInputStream /BufferedOutputStream 及 os.println(), is.readline() 即可。
2. 对于文件的传输,用 FileInputStream /FileOutputStream 及 DataInputStream /DataOutputStream 及 os.write(), is.read() 即可。
3. 对于对象的传输,用 ObjectInputStream /ObjectOutputStream 及 os.writeObject(), is.readObject() 即可 .
Java代码
public class FileSender {
private ServerSocket ss = null;
public FileSender() {
}
public void startSend(String filePath, int port) {
// socket输出流
DataOutputStream os = null;
// 文件输入流
DataInputStream is = null;
// 建立socket连接
Socket socket = null;
try {
// 选择进行传输的文件
File file = new File(filePath);
// 建立socket监听
ss = new ServerSocket(port);
socket = ss.accept();
os = new DataOutputStream(socket.getOutputStream());
// 将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,
// 具体可以参见Think In Java 4th里有现成的代码。
os.writeUTF(file.getName());
os.flush();
os.writeLong((long) file.length());
os.flush();
is = new DataInputStream(new BufferedInputStream(
new FileInputStream(filePath)));
// 缓冲区大小
int bufferSize = 8192;
// 缓冲区
byte[] buf = new byte[bufferSize];
// 传输文件
while (true) {
int read = 0;
if (is != null) {
read = is.read(buf);
}
if (read == -1) {
break;
}
os.write(buf, 0, read);
}
os.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭所有连接
try {
if (os != null)
os.close();
} catch (IOException e) {
}
try {
if (is != null)
is.close();
} catch (IOException e) {
}
try {
if (socket != null)
socket.close();
} catch (IOException e) {
}
try {
if (ss != null)
ss.close();
} catch (IOException e) {
}
} }
public static void main(String[] args) {
new FileSender().startSend("E:\\JDK_API_1_6_zh_CN.CHM", 8821);
} }
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class FileIncepter {
public FileIncepter() {
}
public void getFile(String savePath, String ip, int port) {
// 建立socket连接
Socket socket = null;
try {
socket = new Socket(ip, port);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
// 建立socket输入流
DataInputStream inputStream = null;
try {
inputStream = new DataInputStream(new BufferedInputStream(socket
.getInputStream()));
} catch (IOException e1) {
e1.printStackTrace();
}
try {
// 缓冲区大小
int bufferSize = 8192;
// 缓冲区
byte[] buf = new byte[bufferSize];
int passedlen = 0;
long len = 0;
// 获取文件名称
savePath += inputStream.readUTF();
DataOutputStream fileOut = new DataOutputStream(
new BufferedOutputStream(new BufferedOutputStream(
new FileOutputStream(savePath))));
// 获取文件长度
len = inputStream.readLong();
System.out.println("文件的长度为:" + len + " KB");
System.out.println("开始接收文件!");
// 获取文件
while (true) {
int read = 0;
if (inputStream != null) {
read = inputStream.read(buf);
}
passedlen += read;
if (read == -1) {
break;
}
System.out.println("文件接收了" + (passedlen * 100 / len) + "%");
fileOut.write(buf, 0, read);
}
System.out.println("接收完成,文件存为" + savePath);
fileOut.close();
} catch (Exception e) {
e.printStackTrace();
return; } }
public static void main(String[] args) {
new FileIncepter().getFile("F:\\", "localhost", 8821);
} }
发表评论
-
DirectX编程:C#中利用Socket实现网络语音通信
2012-01-20 10:20 695DirectX编程:C#中利用Socket实现网络语音通信 ... -
Socket编程中的同步、异步、阻塞和非阻塞
2012-01-20 10:20 568Socket编程中的同步、异 ... -
Linux下Socket编程之TCP Server端
2012-01-20 10:20 571Linux下Socket编程之TCP Server端 201 ... -
Socket编程中的select多路复用
2012-01-20 10:20 438Socket编程中的select多路 ... -
范文2
2012-01-19 15:21 468范文2 2010年11月03日 每次作文命题,我总要尽量 ... -
小学生作业做错不打“×”
2012-01-19 15:21 1604小学生作业做错不打“ ... -
活 动 作 文 初 探
2012-01-19 15:21 602活 动 作 文 初 探 2011 ... -
关于农村小学写作教学的几个问题及思考
2012-01-19 15:21 699关于农村小学写作教学的几个问题及思考 2010年12月18日 ... -
2011-8-17
2012-01-19 15:21 3972011-8-17 2011年08月17日 百度帐号XW ... -
Android SDK 2.3与Eclipse最新版开发环境搭建(一)
2012-01-17 05:08 414Android SDK 2.3与Eclipse最新版开发环境搭 ... -
系统是windows2003,数据库是MS SQLServer2000
2012-01-17 05:08 520系统是windows2003,数据库是MS SQLServer ... -
转: Boost下载安装编译配置使用指南(含Windows和Linux)
2012-01-17 05:08 449转: Boost下载安装编译配 ... -
windows编程---在窗口上建立控件
2012-01-17 05:08 558windows编程---在窗口上建立控件 2011年05月3 ... -
标题:Mythroad平台自述----老虎会游泳(精啊!!)-阅(120)
2012-01-17 05:08 834标题:Mythroad平台自述----老虎会游泳(精啊!!)- ... -
使用DevCom和VBS脚本一键开关双网卡
2012-01-16 03:59 814使用DevCom和VBS脚本一键开关双网卡 2009年10月 ... -
将bat代码转换为VBS的工具脚本
2012-01-16 03:59 2074将bat代码转换为VBS的工具脚本 2010年01月14日 ... -
按键精灵 脚本-学习VBS的一个不错的教程
2012-01-16 03:59 594按键精灵 脚本-学习VBS的一个不错的教程 2009年12月 ... -
一个整人的vbs脚本(yzy原创)
2012-01-16 03:59 667一个整人的vbs脚本(yzy原创) 2009年08月30日 ... -
脚本-vbs-有用的脚本
2012-01-16 03:59 521脚本-vbs-有用的脚本 2010年01月15日 ,显示 ...
相关推荐
多线程实现Socket通信 多线程实现Socket通信 多线程实现Socket通信
在主线程中通过控制台读取键盘...服务器在收到一个socket连接之后,把该socket保存到队列中,并对队列中的每个socket开启各自的读写线程。测试可以在不同控制台运行server和client,服务器接收消息时,会显示消息来源
linux下多线程读写socket的简单例子,很容易学习,对于初学者有很大帮助
C语言代码和C++代码--vs2008从指针到多线程、文件读写、套接字 C: 阶乘 冒泡排序 数值转换 行指针、列指针 形状--打印菱形 指针做冒泡排序 6.5指针函数 6.7用指针显示二维数组 7.1文件操作 7.2文件信息提取 8指针...
所谓单个写入程序/多个阅读程序的线程同步问题,是指任意数量的线程访问共享资源时,写入程序(线程)需要修改共享资源,而阅读程序(线程)需要读取数据。在这个同步问题中,很容易得到下面二个要求: 1) 当一个...
QT 内库编写 简单socket one by one 读写 小程序 内有个人编写日志,readme 而且同时上传不断增强的版本,多线程,兼并中英文,局域网聊天程序。。。。请验收
【1】预先分配N个缓冲区,多线程方式对缓冲区进行读写互斥,有类似生产者消费者的思想。 【2】服务器两个线程,一个线程负责读文件进入缓冲区,另一个线程负责发送文件数据。 【3】客户端两个线程,一个线程负责接收...
用来写多线程读写的文档的模拟,主要是为了模拟视频的直播做准备
接着刚才上传的qt socket one by one ,并程,多线程,最终完善了容错,和中英文,基本实现qt 局域网通信小程序。。。注意,阅读readme ,我编写的server 要用我的client 端接收(有设计字符格式问题)。。然后完事...
NIO用于高性能Socket编程由来已久,网络也有较为丰富的原理和源代码。我这里主要介绍几点经验总结: ...本文粘贴多线程在NIO环境下的基本运用示例代码,同时演示了一个线程如何对多个连接进行读写的操作。
继续接着刚才的one by one 和 并程实现一对多的高级版本,多线程,广播,全接受。。。。到此,已经差不多基本实现了局域网通信小程序了。。。。期待进步
Linux物联网网关是基于Linux操作系统的嵌入式网关Server,通过多线程方式实现各种功能。它广泛应用于物联网嵌入式项目,包括参数数据解析、协议转换、Socket收发、Sqlite、Uart、Camera等操作,并提供友好的UI界面。...
多线程处理:通过多线程实现并发处理多个文件传输请求,提高传输效率。 异常处理:处理网络异常、文件读写异常等,确保文件传输的稳定性和可靠性。 应用领域: Java文件传输的实现可以应用于各个领域,包括但不限于...
跟从刚刚传的one by one 的一对多,并程读写版本,下面继续学习完善。。。多线程一对多。。。
Socket通信是网络通信中最常用的技术之一,通过Socket建立的可靠连接,可以让多个终端与服务器保持通信,最典型的应用是建立一个多人聊天程序。本实例使用ServerSocket建立聊天服务器。将服务器端所有的通讯线程保存...
多线程编程:Java中的多线程编程是一种实现并发程序的方法。Java中的多线程通过创建线程对象和实现Runnable接口来实现。多线程编程可以提高程序的并发性和效率。 网络编程:Java中的网络编程是一种实现网络通信的...
该实例主要应用.NET socket实现文件局域网传输,点对点的单文件传输。实例知识点:1、udp网络编程;2、udp局域网广播实现用户的上线下线的提示。3、多线程编程。4、文件的读写。
支持多线程的并发写操作:a)默认情况下,对一个表的写操作都会在一个固定的线程被执行,从而避免可能的死锁;b)也可以通过配置使一个表的写操作被多个线程并发执行,但是可能会导致死锁而进行回滚;c)客户端可以将写...
聊天室的网络通信,socket实现,源码中采用127.0.0.1:9000,用时先开服务端,再开客户端
包括基础知识 、Canvas、RMS 、多线程 、HTTP、Socket、Datagram、文件读写创建删除、PIM、短信彩信、MMAPI、MVC模式等等实例 ---------------以下内容编号对应压缩包内【文件夹号码】---------------- 3用户界面 ...