I have a problem. I want to create a network connection so that I can make a multiplayer game. I know and understand sockets.
My problem is that if I press two keys on the keyboard at the same time it writes to the socket at the same time which causes an error. What I then did was create multiple sockets for one client to writ to and only writes to a socket that isn't busy. By for some reason seems to overload it or something. Any ideas for simultaneously sending messages to server and vice versa.
Is your code doing like this in server?
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new threa for a client
new MyThread(socket).start();
}
then, inside MyThread#run
inp = socket.getInputStream();
brinp = new BufferedReader(new InputStreamReader(inp));
out = new DataOutputStream(socket.getOutputStream());
line = brinp.readLine(); // read the data.
out.writeBytes(line + "\n\r"); //write back to client
out.flush(); // flush socket
Java NIO would faster and efficient. Please refer open source netty servers as well.
I have used a queueing method and has fixed the problem.
Related
I'm setting up a simple program to test starting a server, and I'm getting a silent failure state. My client seems to think it has sent, while my server doesn't think it's recieving. The two are managing the initial connection, it's just sending things after that where it's failing.
I've cut things down to the core of where it's currently failing I think.
Here's part of the Client code
public void Client (int port, String ip)
{
try {
sock = new Socket(ip, port);
System.out.println("Found the server.");
streamInput = new DataInputStream(sock.getInputStream());
// sends output to the socket
streamOutput = new DataOutputStream(
sock.getOutputStream());
streamOutput.writeChars("Client Begining Conversation");
System.out.println(streamInput.readUTF());
}
catch (UnknownHostException u) {
System.out.println(u);
return;
}
catch (IOException i) {
System.out.println(i);
return;
}
}
public static void main(String[] args) throws IOException {
// create the frame
try {
ClientGui main = new ClientGui();
main.Client(8000,"127.0.0.1");
main.show(true);
} catch (Exception e) {e.printStackTrace();}
Here's server code.
public Server(int port) throws Exception
{
ServerSocket gameServer = new ServerSocket(port);
Socket gameSocket = gameServer.accept();
System.out.println("Client has connected");
// to send data to the client
PrintStream dataOutput
= new PrintStream(gameSocket.getOutputStream());
// to read data coming from the client
BufferedReader reader = new BufferedReader( new InputStreamReader(
gameSocket.getInputStream()
));
//play logic
Play(reader,dataOutput);
public void Play(BufferedReader reader, PrintStream dataOutput) throws Exception
{
String received, textSent;
System.out.println("Waiting for response.");
received = reader.readLine();
System.out.println("Client has responded");
//contenue until 'Exit' is sent
while (received != "Exit" || received != "exit") {
System.out.println(received);
textSent = received + "recieved";
// send to client
dataOutput.println(textSent);
}
}
My client gets to here -
Found the server.
and my server gets to here -
Trying to start server.
Client has connected
Waiting for response.
At which point, it just hangs forever, each side waiting for the other. It doesn't throw an error, it just... waits until I force it closed.
So it appears that I'm either doing something wrong when I send with "streamOutput.writeChars" in my client, or I'm doing something wrong when I receive with my server with "reader.readLine();", but I can't figure out what.
Or I could be doing something more fundamentally wrong.
The problem is that reader.readLine() doesn’t return until it sees a new line character, but streamOutput.writeChars("Client Begining Conversation") doesn’t send one.
More generally, mixing a DataOutputStream on the client with a BufferedReader on the server won’t work reliably, as the latter expects plain text, while the former produces formatted binary data. For example, the character encoding might not match. The same applies to communication in the opposite direction with PrintStream and DataInputStream. It’s best to pick either a text based or binary protocol and then be consistent about the pair of classes used on both the client and server.
In the case of a text protocol, an explicit character encoding should be defined, as the default can vary between platforms. As a learning exercise, it might not matter, but it’s a good practice to be explicit about specifying a character encoding whenever handling networked communication. UTF-8 is a good choice unless there’s a specific reason to use another one.
In addition, it is generally preferred to use PrintWriter instead of PrintStream for text output in new code. Read this answer for an explanation.
Hi and thanks in advance.
I am currently trying to create a client server program where the server responds to the client based on different requests coming in from the client.
Here is what I am trying to do for the first of the requests (the issue is the same for all of the clients different requests to the server, so fixing just this would help me fix all of them):
1) The client connects to the server
2) The client sends logon information to the server
3) The server checks the logon information for validity
4) The server sends a response saying that login was successful.
5) Client receives and displays response.
Here is the Client (the first try block is located in the client frame, the second within an action listener for a button on the client frame):
try
{
mySocket = new Socket("localhost", 2016);
}
catch (UnknownHostException e1)
{
e1.printStackTrace();
}
catch (IOException e1)
{
e1.printStackTrace();
}
try
{
DOS = new DataOutputStream(mySocket.getOutputStream());
DOS.writeUTF(txtName.getText() + " " + txtPassword.getText());
DOS.flush();
DOS.close();
DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
JOptionPane.showMessageDialog(null, DISLog.readLine());
}
catch(IOException e1)
{
e1.printStackTrace();
}
Server:
System.out.println("Waiting for client....");
ServerSocket myServerSocket = new ServerSocket(2016);
Socket mySocket = myServerSocket.accept();
myClientHandler = new EZFILEHandler(mySocket);
//Log in check
DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());
StringTokenizer ST = new StringTokenizer(DISLog.readLine());
String Name = ST.nextToken();
String Password = ST.nextToken();
//DISLog.close();
boolean Found = myClientHandler.matchUser(Name,Password);
DataOutputStream DOS = new DataOutputStream(mySocket.getOutputStream());
if (Found == true)
{
DOS.writeUTF("You are logged in.");
DOS.flush();
LoggedIn = true;
}
if (Found == false)
{
DOS.writeUTF("You could not log in.");
DOS.flush();
}
Here is the code for the ClientHandler mentioned in the Server code:
public EZFILEHandler(Socket newConnectionToClient)
{
try
{
mySocket = new Socket("localhost", 2016);
}
catch(Exception e)
{
e.printStackTrace();
}
}
Running the above code will give a Socket is closed exception at this line in the client: DataInputStream DISLog = new DataInputStream(mySocket.getInputStream());, so I then tried commenting out the line: DOS.close(); in the client to keep the socket open, but that causes the button which calls the client code to freeze the program and points to this line if I terminate the program: JOptionPane.showMessageDialog(null, DISLog.readLine());.
So my question is this: How do I allow the client and server to respond to each other in different ways without the socket closing or the jswing freezing from not being allowed to finish processing?
Also, how would it be possible for me to allow multiple clients to logon to the server and all their requests still be processed safely?
Thank you.
If you are writing a Swing program, your socket communication should be on its own SwingWorker thread.
Let's ignore that, and pretend it is just debugging code, not intended to stay.
DISLog.readLine() will read until it reaches the newline character, or the end of the input stream. The server is executing (say) the following:
DOS.writeUTF("You are logged in.");
DOS.flush();
No newline there. And flush() does not close the stream; it simply ensures all the characters are sent, not left in the buffer to be combine with the next set of characters to send.
Catch-22? Yup! The client is waiting for \n, and the server is waiting for more commands from the client.
Change the client to use readUTF().
Update Looks like you need to change the server to use readUTF() as well. The server is probably not getting past the new StringTokenizer(DISLog.readLine()) call unless the client closes the socket.
I have the code below:
while (true)
{
lengthInput = instr.readByte();
// Other code
}
The thing is that I'm using a client to send information to the socket, but after it finishes I got EOF Exception and it brokes the thread, what I need is to manages this and dont stop the thread, because I need to send more information and be able to read it.
Thanks in advance for your help.
I guess the problem is related to your socket initialization. You probably need to check if your client socket indeed successfully create a socket and bind to a specified port. You may also check your client really send data to the outstream and flush to the server side. I have a small project on Android emulators with socket communication. Both my client and serve extends from Java Thread class. Maybe you can gain some idea seeing my code below.
The client side
try {
socket = new Socket(InetAddress.getByAddress(new byte[]{10, 0, 2, 2}),
Integer.parseInt(remote_port));//note we must keep the addr#10.0.2.2
// write out
out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(out_msg);
out.flush();
// read in
in = new ObjectInputStream(socket.getInputStream());
socket.setSoTimeout(1000);
in_msg.set_message((Message)in.readObject());
// close all
out.close();
in.close();
socket.close();
return true;
}catch(InterruptedIOException E){}
The server side
while (true) {
try {
// read in message
Socket ClientSocket = serverSocket.accept();
Message out_msg = new Message();
// read in message
ObjectInputStream in = new ObjectInputStream(ClientSocket.getInputStream());
Message in_msg = (Message) in.readObject();
//Log.d(TAG, "recv" + " content:" + in_msg.msg2Str());
message_process(in_msg, out_msg);
// write out message
ObjectOutputStream out = new ObjectOutputStream(ClientSocket.getOutputStream());
out.writeObject(out_msg);
out.flush();
} catch(Exception E){}
}
I'm writing a proxy and have the following code:
Socket conUser;
Socket conDest;
try{
ServerSocket ss = new ServerSocket(Integer.parseInt(p.getProperty("proxy.port")));
while(true){
//Connect to user
conUser = ss.accept();
BufferedReader inputFromUser = new BufferedReader(new InputStreamReader(conUser.getInputStream()));
BufferedWriter outputToUser = new BufferedWriter(new OutputStreamWriter(conUser.getOutputStream(), "UTF8"));
//Get user request
StringBuffer req = new StringBuffer();
getUserRequest(inputFromUser, req);
System.out.println("User requested the following:");
System.out.println(req);
//Connect to server
InetAddress a = InetAddress.getByName(determineHost(req));
conDest = new Socket(a,80);
//Send request to server
BufferedWriter outputToServer = new BufferedWriter(new OutputStreamWriter(conDest.getOutputStream(), "UTF8"));
InputStreamReader inputFromServer = new InputStreamReader(conDest.getInputStream(), "UTF8");
outputToServer.write(req.toString());
outputToServer.flush();
System.out.println("==============================");
System.out.println("Server replied with the following:");
//Read reply from the server
//=========================================
int chars;
while ((chars = inputFromServer.read()) != -1) {
System.out.print((char)chars);
outputToUser.write(chars);
outputToUser.flush();
//serverReply.append(chars);
}
//Relay reply to user
//outputToUser.write(serverReply.toString());
//System.out.println(serverReply);
//outputToUser.flush();
conUser.close();
conDest.close();
}
}
catch (Exception e) {
System.err.println(e);
}
What happens is: I make a connection and it succeeds. I also send the request, and that succeeds too. I also get a reply, and am able to load the entire page's HTML, except that the read doesn't seem to terminate when it reaches the end of the content.
Specifically, I was attempting to load Google's homepage and the chunked transfer reached 0 (that is- end of chanked transfer), and thus there should've been no more input to read, but this did not cause the loop to stop reading. What's also strange to me is that pretty much all code examples of proxies do use this loop, and assuming they work, I don't see much differences between their code and mine.
How do I make the loop terminate correctly?
EDIT: for the record, yes- I know that the TCP connection should be kept open to handle further connections. This is not relevant to the problem I'm having. I need to get this loop to terminate per response.
In general the connection is not closed at the end of each response. Creating TCP connections is relatively time-consuming so the connection is left open, ready for you to send your next request.
Here are a couple of explanatory links:
http://en.wikipedia.org/wiki/HTTP_persistent_connection
http://en.wikipedia.org/wiki/HTTP_pipelining
If you want to terminate connection correctly after receiving HTTP response, your simple loop is not enough. You have to determine the end of message as described in section 4.4 Message Length of RFC 2616 and then close the connection.
However, it would be better to use existing libraries, such as built-in URLConnection.
I have a Java TCP server which, when a client connects to it, outputs a message to the client every 30 seconds. It is a strict requirement that the client does not send any messages to the server, and that the server does not send any data other than the 30-second interval messages to the client.
When I disconnect the client, the server will not realise this until the next time it tries to write to the client. So it can take up to 30 seconds for the server to recognise the disconnect.
What I want to do is check for the disconnect every few seconds without having to wait, but I am not sure how to do this given that a) the server does not receive from the client and b) the server cannot send any other data. Would anyone please be able to shed some light on this? Thanks.
Even though your server doesn't "receive" from the client, a non-blocking read on the client socket will tell you that either there's nothing to be read (as you expect), or that the client has disconnected.
If you're using NIO you can simply use a non-blocking Selector loop (with non-blocking sockets) and only write on your 30 second marks. If a SelectionKey is readable and the read on the SocketChannel returns -1 you know the client has disconnected.
EDIT: Another approach with blocking is simply to select with a 30 second timeout. Any client disconnects will cause the select to return and you'll know which ones those are via the read set. The additional thing you'd need to do there is track how long you were blocked in the select to figure out when to do your writes on the 30 second mark (Setting the timeout for the next select to the delta).
Big Edit: After talking to Myn below, offering complete example:
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
// Set a 1 second timeout on the socket
clientSocket.setSoTimeout(1000);
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
long myNextOutputTime = System.currentTimeMillis() + 30000;
String inputLine = null;
boolean connected = true;
while (connected)
{
try {
inputLine = in.readLine();
if (inputLine == null)
{
System.out.println("Client Disconnected!");
connected = false;
}
}
catch(java.net.SocketTimeoutException e)
{
System.out.println("Timed out trying to read from socket");
}
if (connected && (System.currentTimeMillis() - myNextOutputTime > 0))
{
out.println("My Message to the client");
myNextOutputTime += 30000;
}
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
Worth noting here is that the PrintWriter really moves you far away from the actual socket, and you're not going to catch the socket disconnect on the write (It will never throw an exception, you have to manually check it with checkError()) You could change to using a BufferedWriter instead (requires using flush() to push the output) and handling it like the BufferedReader to catch a disco on the write.
If you are managing multiple clients then I guess you would be using Non-Blocking sockets (If not then consider using Non-Blocking). You can use Selector to monitor all the connected sockets to check if they are readable or writeable or there is some Error on that socket. When some client disconnects, your Selector will mark that socket and will return.
For more help google "Socket Select function"