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?
Related
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.
So I have network socket class that should be handling my socket connection that i want running when my app is running. Problem is I dont know how to reference the class other than just starting a new one.
To start a new one I would do:
Networker network = null;
try {
network = new Networker(SERVER_IP, SERVERPORT);
new Thread(network).start();
Then i could do:(from the same activity I just did the above in)
network.send("helloworld");
How can i do a network.send in any class without making a whole new socket connection?
Edit:
Here is my Networker Class:
public class Networker implements Runnable, Closeable {
private final Socket clientSocket;
private final PrintWriter out;
private final BufferedReader in;
private volatile boolean closed = false;
public Networker(String hostname, int port) throws IOException {
clientSocket = new Socket(hostname, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public void run() {
try {
for(String fromServer; (fromServer = in.readLine()) != null;)
System.out.println("Server: " + fromServer);
} catch (IOException ex) {
if (!closed)
Log.i("logging", "error") ;
}
}
public void send(String line) {
out.println(line);
}
public void close() {
closed = true;
try { clientSocket.close(); } catch (IOException ignored) { }
}
}
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
Problem:
I have written one java socket server which send response when I send first message from the client to it. But I want to send one more message based on the first response. After the first response i am not getting any other response?
Here is the Server code:
public class SendSmsServerSocket {
private final static CxpsLogger logger = CxpsLogger.getLogger(SendSmsServerSocket.class);
SendSmsServerSocket(){
try {
new SeverSocketForSms(new ServerSocket(4330));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class SeverSocketForSms extends Thread {
private Socket socket;
private ServerSocket serversocket;
private volatile static boolean running = true;
public SeverSocketForSms(ServerSocket ssocket) throws IOException {
this.serversocket = ssocket;
start();
}
public void run() {
try{
while(running) {
this.socket = serversocket.accept();
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : "+msg);
}
}
catch(Exception e){
e.printStackTrace();
}
catch(Throwable t) {
System.out.println("Caught " + t + "xmlServerThread - closing thread");
}
}
public static void shutdown() {
System.out.println("Stopping socket connection and thread");
try{
socket.close();
}catch (Exception e) {
e.printStackTrace();
}
running = false;
}
public static void main (String [] args){
try {
System.out.println("Starting sms server ----- Please press Enter Key to stop the server after receiving one message");
SendSmsServerSocket s=new SendSmsServerSocket();
new Scanner(System.in).nextLine();
SeverSocketForSms.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Once you have an incoming connection, you should delgate the responsibility for handling that incoming connection to another Thread, otherwise you will block your "accept" thread until the current connection is closed...
while (running) {
this.socket = serversocket.accept();
Thread thread = new Thread(new Handler(socket));
thread.start();
}
And the Handler
public class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket){
this.socket = socket;
}
public void run() {
// You may need to add a repeat and exit clause here...
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : " + msg);
}
}