今天老师让写一个服务端和客户端通信的小程序,本以为很快就能写完,但是在写的过程中却发现了自己很多的问题,所以写篇博客记录一下
写完测试的时候发现,客服端只能发第一次数据给服务端,后面发送的服务端都接受不到
//服务端
serverSocket=new ServerSocket(12900);
socket=serverSocket.accept();
inputStream=socket.getInputStream();
byte[] bytes = new byte[1024];
inputStream.read(bytes);
String string = new String(bytes);
System.out.println(string);
//客户端
String mess=message.getText();
outputStream=socket.getOutputStream();
outputStream.write(mess.getBytes());
message.setText("");
后面加上了循环,发现还是只能发送第一次数据
try {
serverSocket=new ServerSocket(12900);
while (true){
socket=serverSocket.accept();//一直阻塞直到有人连接它
inputStream=socket.getInputStream();
byte[] bytes = new byte[1024];
inputStream.read(bytes);
String string = new String(bytes);
// message.append(string+"\n");
System.out.println(string);
}
}
查了资料才知道,socket是阻塞式通信,accep()是会阻塞的和,read()也会阻塞,一直到有东西连接为止,或者有数据可读,所以在这个循环中,第一次的时候因为有客户端连接,所以能够执行后面的代码,输出数据,但后面开始就没有客户端连接,所以就一直阻塞在accept(),导致后面的没法执行
try {
serverSocket=new ServerSocket(12900);
socket=serverSocket.accept();
while (true){
inputStream=socket.getInputStream();
byte[] bytes = new byte[1024];
inputStream.read(bytes);
String string = new String(bytes);
// message.append(string+"\n");
System.out.println(string);
}
}
这样子就能够实现客户端一直给服务端发送数据了
我对上面的程序进行了下改进,加入了线程,每一次有客户端连接时,就建立一个线程处理这个客户端的收发数据,也可借此实现多客户端向服务端通信。
服务端线程类:
public class ServerThread extends Thread {
private Socket socket;
InputStream inputStream
public ServerThread(Socket socket){
this.socket=socket;
}
public void run(){
try {
while (true){
inputStream=socket.getInputStream();
byte[] bytes = new byte[1024];
inputStream.read(bytes);
String string = new String(bytes);
System.out.println(string);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务端:
System.out.println("wait client connect....");
serverSocket=new ServerSocket(8808);
while (true){
socket=serverSocket.accept();//有连接会返回一个Socket,其作为参数传给服务端线程类
System.out.println("client successed !");
new ServerThread(socket).start();//有新的连接就建立一个对应的线程
}
加入线程不好的地方就是,当线程多了会占内存,而你每个线程只执行一点点事情,就会造成内存浪费,而且线程多了,Cpu会在各个线程来回切换,造成Cpu效率低
客户端:
socket=new Socket("localhost", 12900);
String mess=message.getText();
outputStream=socket.getOutputStream();
outputStream.write(mess.getBytes());
message.setText("");
这是本人结合网上的方法,如有不对或者效率更好的方法,欢迎指出和请教。
其实,有个点我没明白,我没关闭输入流和Socket,不是应该是一直连接的吗能够一直接收到数据,为啥还需要循环才能一直接收到数据呢,要是有大佬能看到我这篇,希望帮我解答下,提前谢谢啦