永久性套接字客户端块
问题描述:
我正在为Java中的套接字客户端编码。 在程序中,我想从服务器获取信息。 当服务器收到“GET_LIGHTS”命令时,它将以JSON格式发回数据。永久性套接字客户端块
但在我的代码中,bw.write()
和bw.flush()
在socket.close()
之前不起作用。 因此,BufferedReader对象没有准备好:br.ready()
返回false。
在我的代码中是否有任何错误?
客户端代码如下所示。
package monitor;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
public class SocketClient {
static private int port;
static private String hostName;
private Socket socket;
public SocketClient(String host, int port) {
this.hostName = host;
this.port = port;
}
// get lights by JSON
public void getLights() {
try {
// generate socket
InetSocketAddress endpoint = new InetSocketAddress(hostName, port);
socket = new Socket();
socket.connect(endpoint);
// setting
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
BufferedWriter bw = new BufferedWriter(out);
InputStreamReader in = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(in);
// send command
bw.write("GET_LIGHTS");
bw.flush();
// receive message from server
System.out.println(br.readLine());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void initLights(ArrayList<Light> lights) {
getLights();
}
}
编辑:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class SocketServer extends Thread{
static final int PORT = 44344;
static private ILS ils;
private ServerSocket serverSocket;
private Socket socket;
public SocketServer(ILS ils) {
this.ils = ils;
}
@Override
public void run() {
serverSocket = null;
System.out.println("Server: listening");
try {
serverSocket = new ServerSocket(PORT);
while(true){
socket = serverSocket.accept();
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
ArrayList<String> cmd = new ArrayList<>();
String in;
while((in = br.readLine()) != null){
cmd.add(in);
}
command(cmd);
if(socket != null){
socket.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
if(serverSocket != null){
try {
serverSocket.close();
serverSocket = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
// send message to client
private void sendMessage(String str) {
System.out.println(str);
try {
OutputStream output = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(output));
bw.write(str + "¥n");
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// error
private void printError(String err) {
String str = "ERROR; ";
str += err;
sendMessage(str);
}
public void command(ArrayList<String> cmd) {
String mode = cmd.get(0);
if(mode == null){
}else switch(mode){
case "MANUAL_SIG-ALL":
System.out.println("全照明一括 信号値指定調光");
manualSigAll(cmd.get(1));
break;
case "MANUAL_SIG-INDIVIDUAL":
System.out.println("全照明独立 信号値指定調光");
manualSigIndividual(cmd.get(1));
break;
case "MANUAL_ID-SIG":
System.out.println("照明ID・信号値指定調光");
manualIDSig(cmd.get(1));
break;
case "MANUAL_ID-RELATIVE":
System.out.println("照明ID・相対信号値指定調光");
break;
case "DOWNLIGHT_ALL":
System.out.println("Downlight: All Control");
downlightAll(cmd.get(1));
break;
case "DOWNLIGHT_INDIVIDUAL":
System.out.println("Downlight: Individual control");
downlightIndividual(cmd.get(1));
break;
case "GET_LIGHTS":
System.out.println("Sending lights via JSON");
sendLights();
break;
default:
System.out.println("Error: 不明なmode command");
}
}
// 全照明一括 信号値指定調光
private void manualSigAll(String sigs) {
if(sigs == null) {
System.out.println("信号値のフォーマットを確認してください");
} else {
ArrayList<Integer> s = new ArrayList<>();
String[] buf = sigs.split(",");
for(String i:buf) s.add(Integer.parseInt(i));
for(Light l: ils.getLights()) {
l.setLumPct((double)s.get(0)/255.0*100.0);
l.setSignal(s.get(0), s.get(1));
}
}
// 調光
ils.downlightDimmer.send();
}
// 全照明独立 信号値指定調光
private void manualSigIndividual(String sigs) {
if(sigs == null) {
System.out.println("信号値のフォーマットを確認してください");
} else {
ArrayList<Integer> s = new ArrayList<>();
String[] buf = sigs.split(",");
for(String i:buf) s.add(Integer.parseInt(i));
for(int i=0; i<ils.getLights().size(); i++) {
ils.getLights().get(i).setSignal(s.get(0), s.get(1));
s.remove(0);
s.remove(0);
}
}
ils.downlightDimmer.send();
}
// 照明ID・信号値指定調光
private void manualIDSig(String sigs) {
if(sigs == null) {
System.out.println("信号値のフォーマットを確認してください");
} else {
ArrayList<Integer> s = new ArrayList<>();
String[] buf = sigs.split(",");
for(String i:buf) s.add(Integer.parseInt(i));
System.out.println(s.get(0));
ils.getLight(s.get(0)).setSignal(s.get(1), s.get(2));
}
ils.downlightDimmer.send();
}
private void downlightAll(String cmd) {
if(cmd == null) {
printError("Check for data command.");
} else {
ArrayList<Double> data = new ArrayList<>();
String[] buf = cmd.split(",");
for(String i:buf) data.add(Double.parseDouble(i));
for(Light l: ils.getLights()) {
l.setLumPct(data.get(0));
l.setTemperature(data.get(1));
}
}
// dimming
ils.downlightDimmer.send();
}
private void downlightIndividual(String cmd) {
if(cmd == null) {
printError("Check for data command.");
} else {
ArrayList<Integer> id = new ArrayList<>();
ArrayList<Double> lumPct = new ArrayList<>();
ArrayList<Integer> temp = new ArrayList<>();
String[] buf = cmd.split(",");
if(buf.length % 3 != 0) {printError("invalid number of data.");}
for(int i=0; i<buf.length/3; i++) {
int n = i*3;
try {
id.add(Integer.parseInt(buf[n]));
lumPct.add(Double.parseDouble(buf[n + 1]));
temp.add(Integer.parseInt(buf[n + 2]));
} catch (Exception e) {
printError(e.getMessage());
return;
}
}
while (id.size() > 0) {
// update light object
Light light = ils.getLight(id.get(0));
light.setLumPct(lumPct.get(0));
light.setTemperature(temp.get(0));
// remove data from array list
id.remove(0);
lumPct.remove(0);
temp.remove(0);
}
// dimming
ils.downlightDimmer.send();
}
}
private void sendLights() {
ObjectMapper mapper = new ObjectMapper();
String json = "";
try {
json = mapper.writeValueAsString(ils.getLights());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// output
sendMessage(json);
}
}
答
如果您的服务器使用readLine()
,因为很可能,它会阻止,直到关闭连接,因为你不是发送线。
添加bw.newLine()
之前的flush()
。
编辑正如预测的那样,您的服务器没有发送线路,所以需要与上述相同的处理。但是有一个问题前:
while((in = br.readLine()) != null){
cmd.add(in);
}
这个循环在服务器不可能退出直到客户端关闭连接。您应该一次在服务器上处理一条线,否则会降低您对客户行为的期望。
谢谢你的回答。 我的服务器正在使用'readLine()'。 正如你所建议的,我试图插入'bw.newLine()',但情况是一样的。 – Ryoto
@Ryoto也许你的服务器代码是错误的。你可能不应该在那里使用'br.ready()'。 – Kayaman
@Ryoto让我们看看你的服务器代码。例如,*服务器*发送一行?或者误用'ready()'? – EJP