我有几个客户端尝试使用套接字连接到java程序,所以当两个连接同时到达其中一个没有收到响应时,我在很多帖子中读到服务器时出现问题将响应同时发送给许多客户端,因此我尝试对该响应进行同步阻止但不起作用
我创建一个ServerSocket,等到建立连接并创建一个线程
public class Server{
private static ServerSocket serverSocket;
static int PORT = 8080;
public static void main(String [] args){
try {
serverSocket = new ServerSocket(PORT);
while(true){
ServerThread obj=new ServerThread(serverSocket.accept());
Thread thread =new Thread(obj);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在线程上,我读取客户端发送的输入,解密该输入,处理它,加密响应并将响应发送到客户端
public class ServerThread extends Thread{
final static Logger logger = Logger.getLogger(ServerThread.class);
private Aes aes;
static int SIZE=500;
static int TIMEOUT=10000;
private Socket s;
private ServerSocket serverSocket;
public ServerThread(Socket s) {
this.s=s;
}
public void run() {
try{
System.out.println(this.getName());
System.out.println("Just connected to " + s.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(s.getInputStream());
s.setSoTimeout(TIMEOUT);
int equis = 0;
StringBuilder builder=new StringBuilder();
while((equis=in.readByte())>0){
builder.append(Character.toChars(equis));
}
String valor=builder.toString();
System.out.println(valor);
valor=Encriptacion("decrypt", valor);
System.out.println(valor);
String[] datos = valor.split("\\|");
String tarjeta=datos[0];
double monto=(Double.parseDouble(datos[1].isEmpty()?"0":datos[1]))/100;
int tipoTransaccion=Integer.parseInt(datos[2].isEmpty()?"0":datos[2]);
String numeroSerieTPV=datos[3];
String usuario=datos[4];
String contrasena=datos[5];
String llave=datos[6];
String referencia=datos[7];
String referencia2=datos[8];
int plazo=Integer.parseInt(datos[9].isEmpty()?"0":datos[9]);
int cvv=Integer.parseInt(datos[10].isEmpty()?"0":datos[10]);
int cvv2=Integer.parseInt(datos[11].isEmpty()?"0":datos[11]);
int transaccionId=Integer.parseInt(datos[12].isEmpty()?"0":datos[12]);
int comercioId=Integer.parseInt(datos[13].isEmpty()?"0":datos[13]);
int terminalId=Integer.parseInt(datos[14].isEmpty()?"0":datos[14].trim());
StringBuffer buf = new StringBuffer();
buf.append("");
Transacciones transacciones=new Transacciones();
if(tipoTransaccion==1){
transacciones.compra(tarjeta, monto, comercioId, plazo, terminalId,llave);
}else if(tipoTransaccion==2){
transacciones.pago(tarjeta, monto, comercioId, terminalId,llave);
}else if(tipoTransaccion==3){
transacciones.disposicion(tarjeta, monto,comercioId, plazo, terminalId,llave);
}else if(tipoTransaccion==4){
transacciones.reporte(comercioId, terminalId,llave);
}else if(tipoTransaccion==5){
transacciones.validarUsuario(usuario, contrasena, numeroSerieTPV);
}else if(tipoTransaccion==6){
transacciones.confirmacion(transaccionId);
return;
}else{
transacciones.getEnvioDatos().setCodigoError("0");
transacciones.getEnvioDatos().setDescripcionError("Tipo de transaccion invalido.");
}
buf.append(transacciones.getEnvioDatos().getCodigoError()+"|"
+transacciones.getEnvioDatos().getDescripcionError()+"|"
+transacciones.getEnvioDatos().getFecha()+"|"
+transacciones.getEnvioDatos().getHora()+"|"
+transacciones.getEnvioDatos().getNombreCliente()+"|"
+transacciones.getEnvioDatos().getClave()+"|"
+transacciones.getEnvioDatos().getPromesas()+"|"
+transacciones.getEnvioDatos().getReporte()+"|"
+transacciones.getEnvioDatos().getLlave()+"|"
+transacciones.getEnvioDatos().getTerminalBloqueada()+"|"
+transacciones.getEnvioDatos().getTerminalEstatus()+"|"
+transacciones.getEnvioDatos().getTerminalId()+"|"
+transacciones.getEnvioDatos().getComercioId()+"|"
+transacciones.getEnvioDatos().getTerminalNombre()+"|"
+transacciones.getEnvioDatos().getSucursalId()+"|"
+transacciones.getEnvioDatos().getNombresucursal()+"|"
+transacciones.getEnvioDatos().getDireccionSucursal()+"|"
+transacciones.getEnvioDatos().getPermisoCompra()+"|"
+transacciones.getEnvioDatos().getPermisoDisposicion()+"|"
+transacciones.getEnvioDatos().getPermisoPago()+"|"
+transacciones.getEnvioDatos().getPermisoTiempoAire()+"|"
+transacciones.getEnvioDatos().getCompraMinima()+"|"
+transacciones.getEnvioDatos().getDisposicionMinima()+"|"
+transacciones.getEnvioDatos().getDisposicionMaxima()+"|"
+transacciones.getEnvioDatos().getPlazos()+"|");
if(buf.length()<SIZE) {
while(buf.length()<SIZE)
buf.append("*");
}
String str=buf.toString();
System.out.println(str);
String x=Encriptacion("encrypt", str);
System.out.println(this.getName());
System.out.println("Just connected to " + s.getRemoteSocketAddress());
DataOutputStream out=null;
synchronized(this){
out = new DataOutputStream(s.getOutputStream());
out.write(x.getBytes(Charset.forName("UTF-8")), 0, x.length());
System.out.println(x);
out.flush();
out.close();
}
s.close;
in.close();
} catch(SocketTimeoutException e) {
System.out.println(e);
} catch(IOException e) {
System.out.println(e);
}catch(Throwable e){
System.out.println(e);
}finally{
}
}
}
我阅读了很多网页,但我找不到答案,有人可以帮我找到我的错误吗?
提前致谢
编辑:
我改变了我的代码:
public class Server{
public static void main(String [] args){
ServerThread obj=new ServerThread();
}
}
public class ServerThread {
final static Logger logger = Logger.getLogger(ServerThread.class);
static int SIZE=500;
static int TIMEOUT=10000;
private Socket s;
private static ServerSocket serverSocket;
static int PORT = 8080;
private Object lock=new Object();
public ServerThread() {
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
for(int i=0;i<50;i++){
try {
Thread accept = new Thread() {
public void run(){
try {
s=serverSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(this.getName());
process();
}};
accept.start();
accept.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void process(){
try{
System.out.println("Just connected to " + s.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(s.getInputStream());
s.setSoTimeout(TIMEOUT);
int equis = 0;
StringBuilder builder=new StringBuilder();
while((equis=in.readByte())>0){
builder.append(Character.toChars(equis));
}
String valor=builder.toString();
System.out.println(valor);
valor=encriptacion("decrypt", valor);
System.out.println(valor);
String[] datos = valor.split("\\|");
String tarjeta=datos[0];
double monto=(Double.parseDouble(datos[1].isEmpty()?"0":datos[1]))/100;
int tipoTransaccion=Integer.parseInt(datos[2].isEmpty()?"0":datos[2]);
String numeroSerieTPV=datos[3];
String usuario=datos[4];
String contrasena=datos[5];
String llave=datos[6];
String referencia=datos[7];
String referencia2=datos[8];
int plazo=Integer.parseInt(datos[9].isEmpty()?"0":datos[9]);
int cvv=Integer.parseInt(datos[10].isEmpty()?"0":datos[10]);
int cvv2=Integer.parseInt(datos[11].isEmpty()?"0":datos[11]);
int transaccionId=Integer.parseInt(datos[12].isEmpty()?"0":datos[12]);
int comercioId=Integer.parseInt(datos[13].isEmpty()?"0":datos[13]);
int terminalId=Integer.parseInt(datos[14].isEmpty()?"0":datos[14].trim());
StringBuffer buf = new StringBuffer();
buf.append("");
Transacciones transacciones=new Transacciones();
if(tipoTransaccion==1){
transacciones.compra(tarjeta, monto, comercioId, plazo, terminalId,llave);
}else if(tipoTransaccion==2){
transacciones.pago(tarjeta, monto, comercioId, terminalId,llave);
}else if(tipoTransaccion==3){
transacciones.disposicion(tarjeta, monto,comercioId, plazo, terminalId,llave);
}else if(tipoTransaccion==4){
transacciones.reporte(comercioId, terminalId,llave);
}else if(tipoTransaccion==5){
transacciones.validarUsuario(usuario, contrasena, numeroSerieTPV);
}else if(tipoTransaccion==6){
transacciones.confirmacion(transaccionId);
return;
}else{
transacciones.getEnvioDatos().setCodigoError("0");
transacciones.getEnvioDatos().setDescripcionError("Tipo de transaccion invalido.");
}
buf.append(transacciones.getEnvioDatos().getCodigoError()+"|"
+transacciones.getEnvioDatos().getDescripcionError()+"|"
+transacciones.getEnvioDatos().getFecha()+"|"
+transacciones.getEnvioDatos().getHora()+"|"
+transacciones.getEnvioDatos().getNombreCliente()+"|"
+transacciones.getEnvioDatos().getClave()+"|"
+transacciones.getEnvioDatos().getPromesas()+"|"
+transacciones.getEnvioDatos().getReporte()+"|"
+transacciones.getEnvioDatos().getLlave()+"|"
+transacciones.getEnvioDatos().getTerminalBloqueada()+"|"
+transacciones.getEnvioDatos().getTerminalEstatus()+"|"
+transacciones.getEnvioDatos().getTerminalId()+"|"
+transacciones.getEnvioDatos().getComercioId()+"|"
+transacciones.getEnvioDatos().getTerminalNombre()+"|"
+transacciones.getEnvioDatos().getSucursalId()+"|"
+transacciones.getEnvioDatos().getNombresucursal()+"|"
+transacciones.getEnvioDatos().getDireccionSucursal()+"|"
+transacciones.getEnvioDatos().getPermisoCompra()+"|"
+transacciones.getEnvioDatos().getPermisoDisposicion()+"|"
+transacciones.getEnvioDatos().getPermisoPago()+"|"
+transacciones.getEnvioDatos().getPermisoTiempoAire()+"|"
+transacciones.getEnvioDatos().getCompraMinima()+"|"
+transacciones.getEnvioDatos().getDisposicionMinima()+"|"
+transacciones.getEnvioDatos().getDisposicionMaxima()+"|"
+transacciones.getEnvioDatos().getPlazos()+"|");
if(buf.length()<SIZE) {
while(buf.length()<SIZE)
buf.append("*");
}
String str=buf.toString();
System.out.println(str);
String x=encriptacion("encrypt", str);
System.out.println("Just connected to " + s.getRemoteSocketAddress());
envio(x);
in.close();
} catch(SocketTimeoutException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}catch(Throwable e){
e.printStackTrace();
}finally{
}
}
public void envio(String x){
synchronized(lock){
DataOutputStream out=null;
try {
out = new DataOutputStream(s.getOutputStream());
out.write(x.getBytes(Charset.forName("UTF-8")), 0, x.length());
System.out.println(x);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
但是在向客户端发送响应时仍然存在问题,同步不起作用,我做错了什么?
再次感谢
答案 0 :(得分:1)
总结评论:
多个线程同时在不同套接字上写入没有问题。此外,你的synchronize(this)
没有效果 - 为每个连接创建了一个单独的ServerThread对象(这是一件好事),因此多个线程都有自己的锁,实际上永远不会等待获取锁。你面临的确切问题是什么?尝试在run方法中放置一个断点并逐步执行它。
什么是Encriptacion?也许它不是线程安全的并且需要同步?如果测试发送回简单字符串有效,您可以慢慢地构建它到达您想要的位置。例如,您可以读取所有输入并使用"Just connected to " + s.getRemoteSocketAddress()
等字符串进行响应,这将帮助您验证多线程是否正常工作,同时还可以看到来自不同并发连接的不同响应。
从那里开始,您可以采取一些小步骤 - 我首先会添加解密请求有效负载并将其写回响应(有点像echo服务器)。