线程与网络IO实现简单客户端与服务端聊天交互
首先在学习了线程和网络IO后,做了一个练习.客户端给服务器端发消息.服务器端回消息给客户端.问题由此而生!
服务器类:
public class ThreadServer {
/**
* 在服务器端也写两个内部类实现读与写的分离
* @author 旖析木
*
*/
private class THDL extends Thread{//读的类
private Socket socket ;
public THDL(Socket socket) {
this.socket = socket;//连接当前套接字
}
@Override
public void run() {//从写run方法
DataInputStream in = null;
try {
in = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true) {
String str = null;
try {
String msg = in.readUTF();//读取流中消息
System.out.println("接受到的消息是:"+msg);//打印出来
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private class DLTH extends Thread{//写的类
private Socket socket ;
public DLTH(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
DataOutputStream out = null;
try {
out = new DataOutputStream(socket.getOutputStream());//创建流
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true) {
String str = null;
try {
Scanner sc = new Scanner(System.in);//获取控制台输入
//******就是这里出现错误****因为服务器端的进程里面有两个线程,两个线程公用一个System.in就是抢着回复客户端.所以哪个进程运气好就回给哪个进程
str = sc.nextLine();
out.writeUTF("回消息:"+str);
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(8080);//监听8080端口
System.out.println("服务器开始监听8080端口");
while(true) {//用循环实现可以允许多个客户端连接
Socket socket = ss.accept();//获取到当前连接的客户端
System.out.println("接受一个客户端连接!来电显示"+socket);
THDL th = new ThreadServer().new THDL(socket);//绑定socket 调用写的类
th.start();
DLTH th2 = new ThreadServer().new DLTH(socket);//绑定socket 调用读的类
th2.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端类
public class ThreadCiled {
//写一个内部类用于实现"写"
private class Xie extends Thread{
private Socket socket ;//
public Xie(Socket socket) {
this.socket = socket;//连接当前套接字
}
@Override
public void run() {
String str = null;
Scanner sc = new Scanner(System.in);
do {
try {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
str = sc.nextLine();//通过控制台获取输入
out.writeUTF(str);//用writeUTF写入流中
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}while(true);
}
}
//一个内部类实现"读"
private class Du extends Thread{
private Socket socket;
public Du(Socket socket) {
this.socket = socket;//连接当前套接字进行读
}
@Override
public void run() {
String str = null;
DataInputStream in;
do {
try {
in = new DataInputStream(socket.getInputStream());
str = in.readUTF();//读取传过来流中的数据
System.out.println(str);//打印出来
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}while(true);
}
}
public static void main(String[] args){
String str = null;
Scanner sc = new Scanner(System.in);
Socket socket;
try {
socket = new Socket("localhost", 8080);//连接本地IP8080端口
Xie th = new ThreadCiled().new Xie(socket);//Xie线程调用方法实现写的分离
th.start();
Du xi = new ThreadCiled().new Du(socket);//Xie线程调用方法实现读的分离
xi.start();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这里如果运行两个客户端的话,同时给服务器端发消息 会发生服务器端不知道给哪个客户端回消息的情况!!!如同就像是抢这个sc.next()一样.
出现如此情况,就需要绑定socket来回复!但是目前技术有限,所以日后修改.现在先记录这个问题!