I have a problem with a multi-connected server TCP. It accepts connection to client, but it stuck when it must read data (array of bytes[]) in InputBuffer.
The code is follow:
Server:
public class thread_acc extends Thread{
private final ServerSocket sock_acc;
public thread_acc() throws IOException {
this.sock_acc = new ServerSocket(10000);
}
#Override
public void run(){
for(;;){
try {
Socket sock_client = sock_acc.accept();
System.out.println("connection accepts");
new Thread(new thread_proc(sock_client)).start();
} catch (IOException ex) { Logger.getLogger(thread_acc.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class thread_proc implements Runnable{
private Socket sock_client;
public thread_proc(Socket sock){
this.sock_client = sock;
}
#Override
public void run(){
try {
procRequest();
} catch (IOException ex) {
Logger.getLogger(thread_proc.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(thread_proc.class.getName()).log(Level.SEVERE, null, ex);
}
}
void procRequest() throws IOException, ClassNotFoundException{
byte[] pack1 = socket.readSocket(sock_client);
System.out.println("read pack 1");
byte[] pack2 = socket.readSocket(sock_client);
System.out.println("read pack 2");
.....
}
Client:
public class thread_key implements Runnable {
private static InetAddress IpServer = InetAddress.getByName("127.0.0.1");
private static int PortServer = 10000;
private Socket sock_send;
private int id;
private String namefile;
public thread_key(int id, String namefile) throws IOException {
this.sock_send = new Socket(IpServer, PortServer);
this.id = id;
this.namefile = namefile;
}
#Override
public void run(){
Request();
}
private String[] Request(int iddoc) throws IOException, ClassNotFoundException{
...generations Keys RSA and payloads....
byte[] pack1 = RSA.encryptPub(payload1, pub);
byte[] pack2 = RSA.encryptPub(payload2, pub);
socket.writeSocket(sock_send, pack1);
socket.writeSocket(sock_send, pack2);
System.out.println("write ok");
}
}
Read and Write:
public class socket {
public static void writeSocket(Socket sock, byte[] pacchetto) throws IOException{
ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
out.writeObject(pacchetto);
out.flush();
}
public static byte[] readSocket(Socket sock) throws IOException, ClassNotFoundException{
ObjectInputStream in = new ObjectInputStream(sock.getInputStream());
byte[] pacchetto = (byte[]) in.readObject();
return pacchetto;
}
}
Don't create new object streams every time you want to send or receive something. Use the same streams for the life of the socket, at both ends. Object streams have headers which are read or written on construction, so if construction at the receiver doesn't match construction at the sender, errors will ensue.
Related
I'm writing tests to test the health of the server and client side. In the test, I run the client side, through the creation of the socket, on port 3000. And ServerSocket I also specify port 3000. With normal deployment, everything works correctly. But the test falls apart
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:224)
at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:337)
at java.io.DataInputStream.readUTF(DataInputStream.java:589)
at java.io.DataInputStream.readUTF(DataInputStream.java:564)
at com.epam.preproduction.linnyk.server.factory.TCPServerTest.testGetCount(TCPServerTest.java:54)
My Server:
public abstract class Server implements Runnable {
protected ServerCommand serverCommandController;
private final Socket clientSocket;
public Server(Socket clientSocket) {
this.clientSocket = clientSocket;
serverCommandController = ApplicationContext.getServerCommandController();
}
#Override
public void run() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
BufferedWriter output = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()))) {
checkPortAndConnection(reader, output);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (!clientSocket.isConnected()) {
clientSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public class TCPServer extends Server {
public TCPServer(Socket clientSocket) {
super(clientSocket);
}
#Override
protected String getRequest(BufferedReader input) throws IOException {
return input.readLine();
}
#Override
protected void setResponse(BufferedWriter output, String request) throws IOException {
String result = serverCommandController.execute(RequestParser.tcpParserCommand(request));
output.write(result + "\n");
output.flush();
}
MyTest:
public class TCPServerTest {
private static StoreService productService;
private static Server serverSide;
private static Socket socket;
private static DataInputStream ois;
private static DataOutputStream oos;
#BeforeClass
public static void init() throws IOException {
Main main = new Main();
main.init();
productService = new StoreServiceImpl(new ProductRepositoryImpl());
socket = new Socket(InetAddress.getLocalHost(), 3000);
Runnable server = () -> {
serverSide = new TCPServer(socket);
try {
serverSide.run();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
};
new Thread(server).start();
ois = new DataInputStream(socket.getInputStream());
oos = new DataOutputStream(socket.getOutputStream());
}
#Test
public void testGetCount() throws IOException {
oos.writeUTF("get count");
oos.flush();
String response = ois.readUTF();
int count = productService.getProductMap().size();
String expectedCount = String.valueOf(count);
assertEquals(expectedCount, response);
}
#AfterClass
public static void tearDown() throws IOException {
oos.writeUTF("exit");
oos.flush();
socket.close();
}
I do not understand a bit where I could make a mistake. Can you tell me where the error in the test is? Thank you in advance)
Found an error that in this method to my request is added oos.writeUTF("get count"); /t how can it be removed?
I run this once with boolean "thisIsServer" true and other time false
but the method "message.ChangeA();" doesn't work
(the line System.out.println("message modified"); does't work)
this is main code:
public class Main{
static Semaphore lock = new Semaphore(0);
public static boolean thisIsServer = false;
public static final int port = 8888;
public static Semaphore Lock = new Semaphore(0);
public static Semaphore Lock2 = new Semaphore(0);
public static Message message;
public static String command = new String();
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
if(thisIsServer){
//This is Server
Thread server = new Server();
server.start();
while (true){
Lock.acquire();
message.changeA();
//Lock2.release();
System.out.println("message modified");
}
}else{
//This is Client
Socket socket = new Socket("localhost", port);
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
os.writeObject(new Message(10));
while(true) {
Message returnMessage = (Message) is.readObject();
System.out.println("A is : " + returnMessage.a);
os.writeObject(returnMessage);
}
}
}
}
Server code :
public class Server extends Thread {
public static final int port = 8888;
#Override
public void run() {
//This is Server
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
while (true) {
Main.message = (Message) is.readObject();
System.out.println("message received");
Main.lock.release();
synchronized (this){
wait(1000);
}
System.out.println("message sent");
os.writeObject(Main.message);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
message code:
public class Message implements Serializable{
public Message(int a){
this.a = a;
}
public int a;
public void changeA(){
a = 2*a;
}
}
I think it's because you define Lock in two shape "Lock" and "lock".
But you have used Lock.acquire() for waiting and have used Main.lock.release() when you are unlocking in the thread.
My problem is that for some reason, whenever I want to pipe a string to the server console, the server receives nothing. I've tried to track it down with debugging, but I'm not able to find the issue. I passed a PrintWriter through from MCSERVERPROZESS to the SERVER Runnable and the string I want to pipe through is not null. Here are the codes:
public class MCSERVERPROZESS extends Thread {
private SERVERGUI servergui = null;
private SERVER server = null;
private String serverPath = "/home/mint/mc_server";
private ProcessBuilder builder = new ProcessBuilder("java", "-Xmx1024M", "-Xms1024M", "-jar", "server.jar", "nogui");
public MCSERVERPROZESS(SERVER server, SERVERGUI servergui) throws IOException {
this.servergui = servergui;
this.server = server;
}
#Override
public void run() {
try {
builder.directory(new File(serverPath));
final Process pr = builder.start();
OutputStream stdin = pr.getOutputStream();
InputStream stderr = pr.getErrorStream();
InputStream stdout = pr.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stdout));
this.server.setProcessOutputStream(new PrintWriter(stdin));
String serverOutputText;
do {
serverOutputText= in.readLine();
this.servergui.updateServerArea(serverOutputText+ "\n");
} while (serverOutputText.contains("Stopping server"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public class SERVER implements Runnable {
private SERVERGUI servergui = null;
private int port = 10001;
private ServerSocket serverSocket = null;
private BufferedReader in = null;
private PrintWriter out = null;
private MCSERVERPROZESS mcserver = null;
//private Socket clientSocket = null;
private ArrayList<CLIENTPROZESS> clients = new ArrayList<>();
public SERVER(int Port, SERVERGUI server) throws IOException {
this.servergui = server;
this.port = port;
}
public void run() {
try {
mcserver = new MCSERVERPROZESS(this, this.servergui);
mcserver.start();
servergui.setServer(this);
startServer();
} catch (IOException e) {
e.printStackTrace();
}
}
public void startServer() throws IOException {
this.serverSocket = new ServerSocket(port);
while(true) {
waitForConnection();
}
}
public void waitForConnection() throws IOException {
Socket clientSocket = serverSocket.accept();
this.startConnection(clientSocket);
}
public synchronized void startConnection(Socket s) throws IOException {
new CLIENTPROZESS(s, this).start();
}
void setProcessOutputStream(PrintWriter pw) {
this.out = pw;
}
void sendTextToConsole(String s) throws IOException {
out.write(s);
System.out.println(s);
}
SERVER.sendTextToConsole is used for piping through String to console.
I have a problem with communication between client and server using UDP protocol in Java. I made Client and Server classes and two classes SingleCom responsible for sending and receiving packets.
I tried to test the connection (I run client on one computer and server on another; both create DatagramSocket on the same port) simply by sending "START" string from client to server and after that server should print the string on the console and send back "ACCEPTED", but either client nor server print anything on its console. Could anyone tell me what is going on and why?
Below I show simplified classes (I separated server and client in other packets):
//Client:
public class Client
{
protected static InetAddress serverAddress;
protected static InetAddress clientAdr;
protected static int port;
protected static SingleCom connection;
public static final int PACKET_SIZE = 1024;
public static void main(String[] args) throws IOException, InterruptedException
{
//get server address and port typed from console
load();
connection = new SingleCom();
connection.initilize();
Thread privcastTread = new Thread(connection);
privcastTread.start();
//sending the simplest packet
connection.sendPacket("START", serverAddress);
}
public static synchronized void handlePacket(DatagramPacket packet, String msg) throws IOException
{
if (msg.startsWith("ACCEPTED"))
{
System.out.println("Accepted");
}
}
}
//SingleCom for Client
public class SingleCom implements Runnable
{
DatagramSocket udpSocket;
#Override
public void run()
{
try
{
byte[] buffer = new byte[8192];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while(true)
{
udpSocket.receive(packet);
String msg = new String(buffer, 0, packet.getLength());
Client.handlePacket(packet, msg);
packet.setLength(buffer.length);
}
}
catch (SocketException e)
{
System.exit(1);
}
catch (IOException e)
{
System.exit(1);
}
}
public void initilize() throws IOException
{
udpSocket = new DatagramSocket(Client.port, InetAddress.getLocalHost());
}
public void sendPacket(String text, InetAddress target) throws IOException
{
byte[] sendedMsg = text.getBytes();
DatagramPacket sendedPacket = new DatagramPacket(sendedMsg, sendedMsg.length, target, Client.port);
udpSocket.send(sendedPacket);
}
public void sendPacket(String text) throws IOException
{
sendPacket(text, Client.serverAddress)
}
public void sendPacket(byte[] content) throws IOException
{
//byte[] sendedMsg = text.getBytes();
DatagramPacket sendedPacket = new DatagramPacket(content, content.length, Client.serverAddress, Client.port);
udpSocket.send(sendedPacket);
}
}
//Server
public class Server
{
protected static InetAddress serverAdr;
protected static InetAddress clientAdr;
protected static SingleCom connection;
protected static int port;
protected static int speed; //in KB/s
private static FileOutputStream fos;
public static void main(String[] args) throws IOException
{
load();
connection = new SingleCom();
connection.initilize();
Thread privcastTread = new Thread(connection);
privcastTread.start();
}
public static synchronized void handlePacket(DatagramPacket pakiet, String msg) throws IOException
{
String[] pieces;
if (msg.startsWith("START"))
{
System.out.println(pieces[0]);
connection.sendPacket("ACCEPTED", clientAdr);
}
}
}
//connection for Server
public class ServerCom implements Runnable
{
DatagramSocket udpSocket;
#Override
public void run()
{
try
{
byte[] buffer = new byte[8192];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while(true)
{
udpSocket.receive(packet);
String msg = new String(buffer, 0, packet.getLength());
Server.handlePacket(packet, msg);
packet.setLength(buffer.length);
}
}
catch (SocketException e)
{
System.exit(1);
}
catch (IOException e)
{
System.exit(1);
}
}
public void initilize() throws IOException
{
udpSocket = new DatagramSocket(Server.port, InetAddress.getLocalHost());
}
public void sendPacket(String text, InetAddress target) throws IOException
{
byte[] sendedMsg = text.getBytes();
DatagramPacket sendedPacket = new DatagramPacket(sendedMsg, sendedMsg.length, target, Server.port);
udpSocket.send(sendedPacket);
}
public void sendPacket(String text) throws IOException
{
sendPacket(text, Server.clientAdr);
}
}
I want to send x object over socket but when I run this code i got nothings.
it is stop at new ObjectInputStream(socket.getInputStream())
and don't do any thing else.
Server class:
public class Server {
private static final int PORT = 9001;
ServerSocket listener;
private Handler h[] = new Handler[5];
private int clientCount = 0;
public Server() throws Exception{
System.out.println("The server is running.");
listener = new ServerSocket(PORT);
run();
}
public void run(){
while (true) {
try {
addClient(listener.accept());
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void addClient(Socket socket) throws Exception{
h[clientCount] = new Handler(this, socket,clientCount);
h[clientCount].open();
clientCount++;
}
public static void main(String[] args) throws Exception {
Server s = new Server();
}
}
Handler class // Handle class:
public class Handler extends Thread {
private Server server;
private Socket socket;
private int ID = -1;
private ObjectInputStream obIn = null;
private ObjectOutputStream obOut = null;
public Handler(Server _server, Socket _socket, int i){
super();
server = _server;
socket = _socket;
ID = i;
}
public void open()
{
try {
obIn = new ObjectInputStream(socket.getInputStream());
obOut = new ObjectOutputStream(socket.getOutputStream());
x= ob.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The client:
public class Client {
ObjectInputStream oin;
ObjectOutputStream oot;
private Socket socket = null;
public Client() {
String serverAddress = "127.0.0.1";
try {
socket = new Socket(serverAddress, 9001);
oin = new ObjectInputStream(socket.getInputStream());
oot = new ObjectOutputStream(socket.getOutputStream());
System.out.println("hello i am a client");
oot.writeObject(x);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
Client client = new Client();
}
}
You must declare the ObjectOutputStream before you declare the ObjectInputStream.
When you create an ObjectInputStream, it waits for data from an ObjectOutputStream. It's waiting on that data (the header).
public ObjectInputStream(InputStream in) throws IOException {
verifySubclass();
bin = new BlockDataInputStream(in);
handles = new HandleTable(10);
vlist = new ValidationList();
enableOverride = false;
readStreamHeader(); //this is whats causing it to block
bin.setBlockDataMode(true);
}
protected void readStreamHeader() throws IOException, StreamCorruptedException {
short s0 = bin.readShort();
short s1 = bin.readShort();
if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
throw new StreamCorruptedException(String.format("invalid stream header: %04X%04X", s0, s1));
}
}
If you declare ObjectOutputStream first, it sends the data, which isn't blocking