Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (804)
Games in Android Showcase (239)
games submitted by our members
Games in WIP (868)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Sending data with ServerSocket  (Read 3660 times)
0 Members and 1 Guest are viewing this topic.
Offline Yemto

Senior Devvie


Medals: 4
Exp: 3 years



« Posted 2014-07-31 04:42:46 »

So I have began with doing a turn based rpg game, which going to have multiplayer, but I have run into a problem. I don't know how to send data to a socket without closing it, sure I could make the clients re-connect to the ServerSocket to receive new data, but that seems wrong to me, or is it?

Some code I tested with
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public void sendMessage(Socket socket, String message){
        try{
            OutputStream out = socket.getOutputStream();
            out.write(message.getBytes());
            out.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }
   
    public void sendMessage(String message){
        for(Socket s : players)
            sendMessage(s, message);
    }


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
public class Test {    
    public static void main(String[] args) throws Exception{
        Server server =  new Server(1233);;
        Client client = new Client("127.0.0.1", 1233);
       
        server.sendMessage("Data 1");
        server.sendMessage("Data 2");
       
        Thread.sleep(1000);
        System.exit(0);
    }
}
Offline tkausl

Junior Devvie


Medals: 3
Exp: 5 years



« Reply #1 - Posted 2014-07-31 04:49:06 »

Well, you dont need to close it?!

1  
2  
3  
OutputStream out = socket.getOutputStream();
            out.write(message.getBytes());
            out.close();


Just open the outputStream after the initialisation of the connection and keep it open. If your Client got no data, try to flush() after writing.

My English isnt that great. Correct me, if you want, im still learning this Language Smiley
Offline Yemto

Senior Devvie


Medals: 4
Exp: 3 years



« Reply #2 - Posted 2014-07-31 04:55:46 »

Well, you dont need to close it?!

1  
2  
3  
OutputStream out = socket.getOutputStream();
            out.write(message.getBytes());
            out.close();


Just open the outputStream after the initialisation of the connection and keep it open. If your Client got no data, try to flush() after writing.

Sadly that doesn't work, here is the results.

with close()
1  
2  
3  
4  
5  
6  
7  
8  
9  
Server: Running
Client: attempt to connect
Client: Data 1
java.net.SocketException: Socket is closed
   at java.net.Socket.getOutputStream(Socket.java:943)
   at Pokemon.Server.Server.sendMessage(Server.java:60)
   at Pokemon.Server.Server.sendMessage(Server.java:70)
   at Pokemon.Game.Test.main(Test.java:26)
BUILD SUCCESSFUL (total time: 1 second)


with Flush()
1  
2  
3  
Server: Running
Client: attempt to connect
BUILD SUCCESSFUL (total time: 1 second)


As you can see, only when I close do the client receive the message, and  it only receive the first one.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline tkausl

Junior Devvie


Medals: 3
Exp: 5 years



« Reply #3 - Posted 2014-07-31 04:59:57 »

it seems your client (or server) are shutting down immediately, but with flush it should as good as with close.

My English isnt that great. Correct me, if you want, im still learning this Language Smiley
Offline Yemto

Senior Devvie


Medals: 4
Exp: 3 years



« Reply #4 - Posted 2014-07-31 05:36:59 »

it seems your client (or server) are shutting down immediately, but with flush it should as good as with close.

I don't understand, I have tested with both flush and/or close, but either I get "data 1", or I get nothing.
Offline ewg

Senior Devvie


Medals: 11


Java games rock!


« Reply #5 - Posted 2014-07-31 06:02:53 »

My guess is your doing something like readline in your client read message implementation but it does not look like you are sending any newlines or other delimeters.  But when you call close() the end of stream is making it work.

Also it is technically possible that your main thread could reach the System.exit call before your client gets a chance to print anything.  You should stop the client and server threads in better way and ditch the system.exit call.
Offline orange451

JGO Kernel


Medals: 564
Projects: 8
Exp: 8 years


Your face? Your ass? What's the difference?


« Reply #6 - Posted 2014-07-31 15:59:21 »

Heres two networking methods I wrote like 2-3 years ago. http://pastebin.com/8pCdtr3r
It's a little bit messy...

However, I would recommend looking at the updated nio library for java.

First Recon. A java made online first person shooter!
Offline Riven
Administrator

« JGO Overlord »


Medals: 1371
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #7 - Posted 2014-07-31 17:39:58 »

@orange451: If you share code, you have some responsibility over it, as people may actually use it. Your code is broken in so many ways I'd simply strongly suggest to remove the link to it, as it can only do more harm than good. Emo I'm sorry if that comes across a tad harsh persecutioncomplex

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Offline orange451

JGO Kernel


Medals: 564
Projects: 8
Exp: 8 years


Your face? Your ass? What's the difference?


« Reply #8 - Posted 2014-07-31 20:04:52 »

@orange451: If you share code, you have some responsibility over it, as people may actually use it. Your code is broken in so many ways I'd simply strongly suggest to remove the link to it, as it can only do more harm than good. Emo I'm sorry if that comes across a tad harsh persecutioncomplex
It works perfectly fine for me, and I've used it in a number of projects too o:
It's been tested across the world; all data sent across is sent in the correct order, and also received in the correct order. It's sent quickly, and does not force the client nor the server to hang while waiting for data.

Apart from being "hacky", what is broken about it?

First Recon. A java made online first person shooter!
Offline Riven
Administrator

« JGO Overlord »


Medals: 1371
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #9 - Posted 2014-07-31 21:36:05 »

Okay, since you asked for it...

1  
2  
public int receivemessage(Socket client) {
        int amountBytes = 0;

The following try/catch block does nothing like the comment states
1  
2  
3  
4  
5  
        // This try catch is to trick the socket into being non-blocking when checking for data
        try {
                InputStream stream = client.getInputStream();
                amountBytes = stream.available();
                this.in = new DataInputStream(stream);

Using a DataInputStream directly on top of a socket InputStream will lead to many single-byte reads from the socket, which means we visit kernel space for every byte we read. You most likely intended to use a BufferedInputStream.

1  
2  
        } catch (Exception localException) {
                //

You just threw away the cause of a crash, ignoring it, and moving on... this aint PHP.

1  
2  
3  
4  
5  
6  
7  
        }
       
        // I there's incoming data, then read it
        int msg = 0;
        if (amountBytes > 0) {
                try {
                        msg = this.in.read();

'msg' holds an integer between -1 and 0xFF, let's ignore -1, because... there were bytes available, right? A bigger problem is that your packets can be at most 255 bytes long, that's tiny, that's even smaller than the usual size of IP packets.

1  
2  
3  
4  
                        this.buffer.in.clear();
                        this.buffer.inpointer = 0;
                        for (int i = 0; i < msg + 1; i++) {
                                int read = this.in.read();

--> nasty bug <--
That there are 'amountBytes>0' bytes available, doesn't mean we can assume 'amountBytes>=msg+1', so the 'read' operation can start returning -1 once the buffer is depleted. Any actual data you read from the socket from that point on, will not be adhering to your protocol, as you're reading bytes from the remainder of a previously received packet. That you sent X bytes, does not mean you are guaranteed to be able to read X bytes in one go, on the other end. Read up on TCP packet fragmentation.
Yet again, we're doing 1 kernel space operation per byte we read from the socket buffer, this can bring even a fast server to its knees with a handful of connections.

1  
                                if (i > 0)

You just discarded the first byte of the packet - as if it's meaningless, just filler.

1  
                                        this.buffer.append(read);

You seem to store 8 bits worth of data as an 32 bit integer.

1  
2  
3  
                        }
                }
                catch (Exception localException1) {

Let's ignore anything that could go wrong, like a remote endpoint closing the connection, it's better not to know, as then you don't have to handle it either...

1  
2  
3  
                }
        }
        this.in = null;

You just nullified a field that was assigned at the start of the method. This should be a local variable.

1  
2  
3  
4  
5  
6  
        return msg;
}
 
public void sendmessage(Socket socket) {
        try {
                if (socket != null) {

You are silently failing when somebody tried to send data to a null-socket.

1  
2  
3  
4  
                        OutputStream outst = socket.getOutputStream();
 
                        BufferedOutputStream bos = new BufferedOutputStream(outst);
                        if (bos != null) {

How can 'bos' possibly be null here?

1  
                                bos.write(this.buffer.out.size());

Silent failure (!) when the packet size is over 255.

1  
                                bos.write(0);

Here we have this meaningless byte, that we discard on the other end... why oh why...

1  
2  
                                for (int i = 0; i < this.buffer.out.size(); i++) {
                                        int bytesend = ((Integer)this.buffer.out.get(i)).intValue();

Every outbound byte is held as an Integer object... or is this an attempt at a cast to int ?!

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
                                        bos.write(bytesend);
                                }
 
                                this.buffer.in.clear();
                                bos.flush();
                        }
                } else {
                        this.buffer.in.clear();
                }
        } catch (Exception e) {
                //

Blindfolds and earplugs galore.

1  
2  
        }
}





The general API seems totally off: we compose a packet, and send it to an arbitrary Socket. Maybe you're broadcasting an identical packet to N clients, but generally a packet is composed for a specific client, so passing in an abitrary Socket instance, and sending that packet to it, is the wrong way around. Completely discarding all bytes in the packet, the moment this arbitrary Socket happens to be null, is just odd.



Another oddity:
receivemessage(Socket) is non-blocking
sendmessage(Socket) is blocking!

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Pages: [1]
  ignore  |  Print  
 
 

 
Riven (581 views)
2019-09-04 15:33:17

hadezbladez (5510 views)
2018-11-16 13:46:03

hadezbladez (2402 views)
2018-11-16 13:41:33

hadezbladez (5772 views)
2018-11-16 13:35:35

hadezbladez (1223 views)
2018-11-16 13:32:03

EgonOlsen (4661 views)
2018-06-10 19:43:48

EgonOlsen (5682 views)
2018-06-10 19:43:44

EgonOlsen (3198 views)
2018-06-10 19:43:20

DesertCoockie (4095 views)
2018-05-13 18:23:11

nelsongames (5115 views)
2018-04-24 18:15:36
A NON-ideal modular configuration for Eclipse with JavaFX
by philfrei
2019-12-19 19:35:12

Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!