我用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);
}
}
答案 0 :(得分:2)
如果您的服务器正在使用readLine()
,那么它将会阻止,直到您关闭连接,因为您没有发送一行。
在bw.newLine()
之前添加flush()
。
编辑正如预测的那样,您的服务器没有发送线路,因此它需要与上述相同的处理方式。然而,有一个前面的问题:
while( (in = br.readLine()) != null ){
cmd.add(in);
}
服务器中的此循环不能退出,直到客户端关闭连接。您应该在服务器中一次处理一行,或者调整您对客户行为的期望。