[b]面对socket客户端每分钟发送一次信息,这段java-socket服务端程序是否稳定?有哪里可以改进?[/b]
[code="java"]
package test;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServeSocket{
//private static Logger logger = Logger.getLogger(ServeSocket.class);
private Socket socket;
private ServerSocket serverSocket;
//端口
private int socketPort = 10000;
//队列长度
private int queueLength = 10;
//IP地址
private String socketAddress = "127.0.0.1";
private ExecutorService executeService = Executors.newFixedThreadPool(10);
private BufferedReader br;
private FileOutputStream fos;
private OutputStreamWriter out;
public void serveSocketProgram(){
try {
serverSocket = new ServerSocket(socketPort,queueLength,InetAddress.getByName(socketAddress));
while(true){
socket = serverSocket.accept();
executeService.submit(new Runnable() {
public void run() {
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(br.read()!=-1){
String message = br.readLine();
System.out.println(message);
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
br.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new ServeSocket().serveSocketProgram();
}
}
[/code]
有几个问题
1、你的IP绑定了127.0.0.1,只能接受本机发来的请求。建议为0.0.0.0,绑定所有网卡
2、每读一次readLine,都会丢弃一个字节,因为你用read!=-1判断。建议通过do while的模型判断readLine是否返回的为null
3、使用readLine在网络编程中不是好习惯,因为这要求对方必须发送换行符过来,如果没有你就一直等待直至超时。所以建议双方协商好协议,通过传输一个header,通过一个int标识body部分有多少个字节,然后直接创建相同大小的数组获取传输的流的信息
4、文字编码格式和字节序。如果传输的是文本,是UTF-8格式吗?双方要商定好。如果有int、long等类型,那就需要考虑字节序了。java传输的是标准的网络字节序
5、BufferedReader应该是局部变量,否则会出问题的。
5、每收到一行就println,这样会导致多个线程的时候输出的内容混乱。建议内容先存放到一个StringBuilder中(局部变量),然后一次性的打印出来。
还有一些改进意见
1、是否考虑改为nio,如果只是传输一些消息,目前的bio效率很低。
2、客户端一分钟发送一次,那么有多少个客户端会同时发过来呢?并发的问题的考虑。
3、建议考虑一个服务的退出机制,首先建议使用一个单独的用户线程来做这个消息的循环,同时设定一个标志位,遇到false就退出。避免使用while(true),另外要响应一些中断异常等,这些就不多说了java并发里面说的很清楚。
有什么问题直接私信问我吧
有,有个线程安全的问题
你的BufferedReader应该只关联一个socket的
而不是所有的socket都关联一个BufferedReader
这样会引起你的消息混乱
1 多个线程绑定同一IP、端口是不行的:
别用多线程
2 多个线程共享一个socket是不行的:
把socket定义写到while里面
while(br.read()!=-1){
String message = br.readLine();
System.out.println(message);
}
br.read和br.readLine,这两者重复了,br.read返回的东西直接被你丢弃了。你这样会造成客户端发送东西很不方便。
首先不应该在死循环中放入线程,会造成线程混乱。应该在线程中启用循环去连接。
建议在处理socket stream的时候,直接按字节读,之后对字节不是按换行符读取,你可以做一个编码协议层,将来要更换协议也更方便。
另外,socket本身也可以加上超时soTimeout,防止长时间阻塞一直占有线程。