基于TCP 的多线程 聊天程序
2008-05-07 10:02
423 查看
/**//*
* 功能:聊天的客户端
*soft05jun
*08.3.12
*/
import java.net.*;
import java.util.*;
import java.io.*;
class connet implements Runnable
...{
Socket localsocket;
DataInputStream in=null;
DataOutputStream out=null;
Thread send,rec;
Scanner read; //读入流对象
connet(String address,int port)
...{
send=new Thread(this);
rec=new Thread(this);
read=new Scanner(System.in);
try
...{
localsocket=new Socket(address,port);
in=new DataInputStream(localsocket.getInputStream());
out=new DataOutputStream(localsocket.getOutputStream());
}
catch(IOException e)
...{
System.out.print("套接字创建失败,原因:"+e);
System.out.println("请检查服务器IP、端口是否正确");
}
System.out.println("连接成功,可以进行聊天了");
send.start();
rec.start();
}
public void send()
...{
while(true)
...{
try
...{
out.writeUTF(read.nextLine());
}
catch (IOException e)
...{
System.out.println("写入信息时失败");
}
}
}
public void rec()
...{
while(true)
...{
try
...{
System.out.println(in.readUTF());
}
catch(IOException e)
...{
System.out.println("读取服务器信息失败");
}
}
}
public void run()
...{
if(Thread.currentThread()==send)
...{
System.out.println("send线程启动,进入发送状态");
this.send();
}
if(Thread.currentThread()==rec)
...{
System.out.println("rec线程启动,进入接收监听状态");
this.rec();
}
}
}
class client
...{
public static void main(String args[])
...{
String ip=null;
int port=2526; //默认是2526
try
...{
ip=new String(InetAddress.getLocalHost().getHostAddress());
}
catch(Exception e)
...{
System.out.println("获取本地IP地址出错,请检查本地网络连接。");
}
Scanner reader=new Scanner(System.in);
System.out.println("请输入服务器IP:");
ip=reader.nextLine();
System.out.println("服务器端口:");
port=reader.nextInt();
System.out.println("正在连接服务器的IP地址是:"+ip+" 端口是:"+port);
connet c=new connet(ip,port);
}
}
import java.net.*;
import java.util.Scanner;
import java.io.*;
import java.util.*;
/**//*
* 此是服务器端
* soft05jun
* 08.3.14
* 改进:其实current_thread,thread_num,mslist等变量可以声明为全家的静态变量比较好。这样就
* 省掉了 传递的开销。
*/
class message //消息类.
...{
int id=0;
String ms;
message(int id,String ms)
...{
this.id=id;
this.ms=ms;
}
}
class serverconnet //服务器监听线程
...{
ServerSocket localsocket;
LinkedList<message> mslist;
static Vector current_thread;
static int threadnum;
serverconnet(int port)
...{
try
...{
localsocket =new ServerSocket(port);
}
catch(IOException e)
...{
System.out.println("服务器端套接字创建失败,请检查端口是否冲突。如冲突,请换用其它端口");
}
mslist=new LinkedList<message>(); //消息链表(用队列比较好.)
current_thread=new Vector(); //在线列表.(线程列表哦)
threadnum=current_thread.size(); //线程数目.(用 在线容器 里线程数量来赋值)
new control(mslist,current_thread).start(); //启动控制线程.(其实这个时候启
//动未必好,因为当没有客户连接过来时,它子线程也一直在运行.浪费CPU
}
public void work()
...{
System.out.println("正在监听~");
Socket s=null;
while(true)
...{
try
...{
s=localsocket.accept();
System.out.println("接收到一个客户连接请求,它的地址:"+s.getInetAddress());
}
catch(IOException e)
...{
System.out.println("接受连接请求出现异常~");
}
if(s!=null)
...{
xiancheng thread=new xiancheng(s);
System.out.println("当前线程编号:"+threadnum);
thread.setid(threadnum); //线程ID设置.
thread.setmsg(mslist); //将此 消息队列 传参过去.
current_thread.add(threadnum,thread); //加入在线列表.第一个参数为此对象的索引,类似数组下标。
threadnum++;
thread.start();
}
}
}
public static void remove(int id)
...{
current_thread.remove(id);
threadnum--;
}
}
class control extends Thread //控制线程
...{
LinkedList<message> mslist;
Vector current_thread;
int threadnum; //在线线程数目。
String ms=null;
control(LinkedList<message> mslist,Vector current_thread)
...{
this.mslist=mslist;
this.current_thread=current_thread;
}
public void run()
...{
while(true) //这里写得并不高效.可以把链表操作次数再减少,以提高效率.
...{
if(mslist.isEmpty())
...{
try
...{
Thread.sleep(1000);
}
catch(InterruptedException e)
...{
System.out.println("线程休眠失败.");
}
continue;
//Thread.yield(); //测试发现,此函数并没有很好提高CPU性能,反而是占用率100%
}
else
...{
threadnum=current_thread.size();
ms=new String("线程ID为:"+mslist.getFirst().id+"的客户说:"+mslist.getFirst().ms);
for(int i=0;i<threadnum;i++)
...{
xiancheng thread=(xiancheng)current_thread.elementAt(i);
thread.send(ms);
}
mslist.removeFirst();
}
}
}
}
class xiancheng extends Thread //服务线程
...{
DataOutputStream out=null;
DataInputStream in=null;
String ms=null;
Socket socket;
Scanner read; //读入流对象
String shiyan;
LinkedList<message> msglist;
int id=0;
xiancheng(Socket s)
...{
socket=s;
try
...{
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
}
catch(IOException e)
...{
System.out.println("这里出现异常~");
}
}
public void run()
...{
while(true)
...{
try
...{
msglist.add(new message(id,in.readUTF()));
}
catch(IOException e)
...{
System.out.println("读写异常~,客户端可能已经退出。");
serverconnet.remove(this.id); //调用static 方法,移除在线列表。
break;
}
}
}
public void send(String ms)
...{
synchronized(out) //线程同步~~~~~!!!!!!!!!
...{
try
...{
out.writeUTF(ms);
}
catch(IOException e)
...{
System.out.println("线程同步异常:"+e);
}
}
}
public void setid(int threadnum) //设置线程编号.
...{
this.id=threadnum;
}
public void setmsg(LinkedList<message> mslist) //设置消息链表.
...{
this.msglist=mslist;
}
}
public class server
...{
public static void main(String args[])
...{
int port=2526;
System.out.println("请输入服务器监听端口号");
Scanner reader=new Scanner(System.in);
port=reader.nextInt();
serverconnet ss=new serverconnet(port);
System.out.println("服务器正在监听"+port+"端口,等待客户连接");
ss.work();
}
}
相关文章推荐
- Qt实用技巧:基于tcp的C/S构架多人聊天程序(在线、离线、离线信息再次登录后发送等)
- 利用TCP传输协议实现基于Socket的聊天程序
- 基于TCP的网络聊天程序
- 基于socket、多线程的客户端服务器端聊天程序
- 基于tcp交互的python聊天程序
- Linux Linux函数 Linux聊天程序 基于socket的TCP(有连接的)聊天程序
- 基于TCP/IP的简单的聊天程序
- 4000 基于DES加密的TCP聊天程序
- 基于TCP的聊天程序(了不起的nodejs chapter6)
- 基于Linux的Socket编程之TCP全双工Server-Client聊天程序
- C++基于socket的单线程服务器客户端聊天程序(TCP)
- 基于Tcp通信的聊天程序微风IM(c#开源) -技术分析(一) 用户管理
- Java Socket编程 - 基于TCP方式的客户服务器聊天程序
- 基于Tcp通信的聊天程序微风IM(c#开源) -技术分析(一) 用户管理
- 基于socket、多线程的客户端服务器端聊天程序
- 基于socket的Linux上的网络聊天程序--多线程的服务器
- 一个基于TCP的聊天程序
- 基于TCP与UDP的简单聊天程序
- 基于TCP的python聊天程序(2)
- Linux 下基于多线程服务器/客服端聊天程序源码