sending client file to server back to client in Real time

Started by
16 comments, last by grumpyOldDude 7 years ago

This one is easy. Remember the network code splits your big data block into a lot of small packets and sends each of them to the other side? These packets do not arrive all at the same time, so if you read at the other side, and a bunch arrives, the kernel gives you what it received so far, up to the length you requested. Normally, it is less than what you asked for,

After reading the InputStream.read description, and your buffer loop reader, it starts to make sense, but it's a few steps before you arrive there. The first thing what you must do is to stop using code that you do not fully understand. If you don't entirely understand your "read buffer" loop code, you're coding the higher levels on top of "I think it might do X", for some unknown value of X. Together with the inherently random nature of network IO wrt timing, speed, and bandwidth, you get what you experience, seemingly random behavior that works and then breaks again. The only way forward is to exactly know what X is. You do that by writing your own "read buffer" loop from the InputStream.read documentation. That way, you know the purpose of each and every statement, you know exactly what to expect from that low level function, and you can stack the higher level code on top of known functionality. So as homework, I'd suggest you write your own "read data into buffer" loop, using only the description of InputStream.read. Afterwards, compare notes, where does your implementation work differently from the $random website one? My guess is you'll do the "-1" case differently, in particular, after receiving all data that you need. The second thing you must do is to stop thinking in server-only and client-only. It seems to me you're coding a server, and you;re coding a client, then run them both and hope it works. In networking, failure and blocking can have 3 causes. A) Server code can be wrong, B) Client code can be wrong, C) Either side can get blocked or die or whatever, due to things that the other side does or does not do. The 3rd item is what is causing your blocking. To get a handle on this, you can draw the interactions between the server and the client with a message sequence chart

once again your assistance has helped solved this problem.

The key was (1) file-data come in smaller chunks (packets) and (2) fully Understanding the code and thus the need for two read().and current = bytesRead; line code. And if instead of 'current' it was named 'chunk', i would have understood it better

The knowledge of 1. made understanding the read()s code very simple. The first read() was to accept the first chunk that was then used to calculate the remaining bytes for the 3rd parameter of read(). And inside the do-while loop, bytesRead continues to add up to small chunks, which goes back to calculate the remainder length-size to be read until finished.

Once I knew this it wasn't to difficult to find where the problem was. the BufferedInputStream object -> bis wasn't closed. If the jpeg file was already saved, bis doesn't need to be closed. But if the server is writing the file at run time, it can't complete the write without bis closed. So once I closed bis, I was able to send the same file save at the server at run time. Even if it read the file in one big swoop bis would still need to be closed, but understanding the concept deeper was the key that made realise closing bis needed was fix.

ripoff gave a hint on this but joining the dots of these hints bit by bit to get a proper overview is not always possible for me

What still annoys me though is every time I try to make another step forward i always encounter a snag. Right now, I can send files from client to server, save, and send the same back to client. So in the server code, after sending a jpg file, i now also sent a text file with String data to client. But when I opened the text file at the client (on my android phone), it didn't contain the string-text. It opens well (which means it wasn't corrupted or something like that) but it just didn't have any string-text data in it that was in the original text file from server.

Its really annoying but this however is where i am stuck at again, why is the text-file empty when I open it at the client device?

My additional text file with string text.

This is the additional code, the rest is as in the code above (in post 3). Many thanks anyone who helps


 Server code
            ...
            ...
         File pathPlusfile = new File("C:\\rootFolde\\renderData.txt");
         appendToFile( pathPlusfile, "This my crap string text here just for test", 31  );
                
//==================   Send Data to Client  ============================================              

          mybytearray  = new byte [(int)pathPlusfile.length()];
          fis = new FileInputStream(pathPlusfile);
          bis = new BufferedInputStream(fis);
          bis.read(mybytearray,0,mybytearray.length);
          os = sock.getOutputStream();
  
//========================== send file to client ===================                
          os.write(mybytearray,0,mybytearray.length);
          os.flush();
          bis.close();
          ...
          ...

   static BufferedWriter  bufferedWriter = null;

    public static void appendToFile( File myPathPlusFile, String S, int num  ){
 	   
  	   try{
  		  bufferedWriter = new BufferedWriter(new FileWriter(myPathPlusFile, true));
  		  bufferedWriter.write( S ); 
  	          bufferedWriter.newLine();
  		  bufferedWriter.append( S ); 
  		  bufferedWriter.append( "     " ); 
  		  bufferedWriter.append( Integer.toString(num) ); 
  	      bufferedWriter.newLine();
  	      bufferedWriter.flush();
  	   }
  	   catch (IOException e){
  	      e.printStackTrace();
  	   }
    	  closeFile(  );
     }

public static void closeFile( ){
try
bufferedWriter.close();
}
catch (IOException e)
{
e.printStackTrace();
}

}

I don't mind posting questions where i am stuck at but when i get stuck at every single point I try to make progress it makes me look so dumb :wub:


Moving this to Networking. Please don't post in other forums just because one is quiet; it's not meant to be a real-time chat system but a categorised forum.

[Note: the stuff below is not written with a bad attitude or hash tone. Its just me giving my good and valid reason]

There is a very good reason for this

1. I agree this is a voluntary thing and not everyone can be here all the time, so my mentioning of this forum being quiet over the weekend wasn't a complain in any sense. Rather I appreciate the great assistance and help experienced people give those of us with less skills and experience

2. Because of my day job (weekdays) I have more time to work on my project during weekends than during weekdays. (I still have time during the week but i have more opportunity of doing marathon hours on my project at weekends). There are also lots of interruptions for me during weekdays

3. I had placed threads here before on Friday night and only one person replied to it, but I needed more than what they gave but I never had one till mid-monday, whereas there are lots of other users who would have helped but don't just visit this sub-forum that much.

And that makes a waste of my optimsed periods of weekends

Alberth who had been extremely helpful even mentioned it in the other thread that he doesn't visit here that much.

Thanks for your little note, networking forum is not visited regularly by me, so I missed the next problem

So I wasn't expecting a chatroom kind of conversation rather I was giving more people who can help the opportunity to see my thread at the time when I am also able to work on my project and their advice the most

4. More so the thread can still be classified as programming in general, so it doesn't break anything by placing this under general programming. Its not as wild as placing a game design question, Lounge question, visual arts question or business and law question in the general programming forum

5. Other mods often see my client server question there a few times and have been ok with it.

6. The advantage of forums is the different global time zones and this means when one is sleeping others can be awake It. It is also a fact that the ratio of visits during the weekends of GP forum to here is probably roughly 10:1 (where 1 here means one or two people) thus it will be counter productive for a weekend project-person to stick here because of the mild deviation between general programming and network programming

7. And I forgot to mention that you didn't even put the suitcase moved-post icon there, This thread just "disappears". So maybe other people I'm trying to reply to wouldn't even see this post

So in conclusion my need to place networking code threads in GP forum is, - I want to maximise (and not waste) my weekends. not that i was expecting a chat service

(I'm mostly a weekend project person [though i also have a lot of interrupted times during the week] and I gained a lot this past weekend and don't want to miss that in future because of this kind of bureaucracy. That's why I've gone at length to make this case. But it is all with respect, not personal)

can't help being grumpy...

Just need to let some steam out, so my head doesn't explode...

Advertisement

Is this a limitation of client server - is it the way it is meant to work? or am I doing something wrong?


The ONLY thing the client knows is the bytes sent by the server. Nothing else. It doesn't know if your server is the same machine, or a virtual machine in a server room downtown, or a smart monkey generating packets by quickly transcribing hex to/from slips of paper.

Other than that, the recommendation I can give is to print and verify EVERY return value from EVERY function. Both on the server and client.
For example, if you get an error sending "the same" file back, is that because of permissions? Does your server still hold the file open for writing, and trying to re-open it for reading fails with a permission error, for example?
Do you get the number of bytes you expect in each call to receive? If not, what is your fallback strategy?

In general, network protocols will want to store incoming data into some kind of buffer, and then look to see if there's a full packet in that buffer yet. If so, read it out, and remove it from the buffer (save anything that's not part of the package you processed!) If not, read some more, and try again. This is the #1 important pattern to use when talking to a network!
enum Bool { True, False, FileNotFound };

So in conclusion my need to place networking code threads in GP forum is, - I want to maximise (and not waste) my weekends. not that i was expecting a chat service
(I'm mostly a weekend project person [though i also have a lot of interrupted times during the week] and I gained a lot this past weekend and don't want to miss that in future because of this kind of bureaucracy. That's why I've gone at length to make this case. But it is all with respect, not personal)


You're missing one crucial thing; the forum is for everyone. So while you might be right in thinking "I will get more help if I post in General Programming", other people may be thinking "I'm not interested in networking questions; why are they here in General when they have their own subforum"? Other people may also, in future, do a search of this specific subforum to find useful threads on a similar topic, but this thread wouldn't have shown up as it was in the wrong place. And some people with specialist knowledge only view certain subforums, so they will never see your post if it is in General. Hplus0603, for example, hasn't posted outside this subforum for years.

The different subforums are there for a reason. I appreciate it's frustrating to not get help in a timely manner when we can't spend much time on our projects, but it's in everyone's general interest to keep things organised.

As for your actual (most recent) question: the code is too cluttered now to give any serious feedback on it. We can't go comparing multiple snippets to try and work out how to piece them together. You say you're sending a file which isn't getting written on the client, but the code you've posted shows it getting written on the server, or at least isn't clear about where that file-writing code lives. I suggest tidying up the formatting, reducing or removing all the static variables (for example, 'appendToFile' should have its own BufferedWriter, not overwrite some shared static), remove any code that isn't essential for diagnosing the current problem, add the logging/checking that Hplus0603 recommended, and then post it up if necessary.

But when I opened the text file at the client (on my android phone), it didn't contain the string-text. It opens well (which means it wasn't corrupted or something like that) but it just didn't have any string-text data in it that was in the original text file from server.

Baesides dumping info on number of bytes etc received, also split file-io problems from network-io problems by adding a (temporary, perhaps) buffer.

Get stuff from the network to the buffer, and dump the buffer to the screen, or verify it has the text/data you expect, or whatever it takes to verify the data is unchanged[1] in that buffer.

Any problems with files not working are then already shown not to be caused by network communication.

Edit: [1] means "unchanged wrt what you expect to receive"

]I appreciate it's frustrating to not get help in a timely manner when we can't spend much time on our projects


In addition: :If the only way you can think of for debugging a program is "ask on a forum," then you need to learn more about various debugging techniques.
Debugging techniques may include:
- turning on all compiler warnings and paying attention to the output
- printing inputs and outputs
- stepping through code in a debugger
- using a static code analyzer and paying attention to its output
- commenting out various bits of code and verify assumptions about behavior
- copy and pasting small snippets of code to small external programs to verify behavior
- (re-)reading the documentation about the various functions used and thinking about every word in the described behavior
enum Bool { True, False, FileNotFound };

reducing or removing all the static variables (for example, 'appendToFile' should have its own BufferedWriter, not overwrite some shared static),

I can see what you are saying, but I was forced to make 'appendToFile' static because 'main(String[] args)' is static. If I don't a compile error is flagged


Cannot make a static reference to the non-static method appendToFile(File, String, int) from the type 
FileServer 

And obviously removing static from main() doesn't run


Error: Main method is not static in class server.FileServer, please define the main method as:
   public static void main(String[] args) 

That's a good point, could be the reason for the file at client not containing the string ... and I need to investigate.

If Java is one of the languages you code with, then do you know how I can make appendToFile non-static when the compiler is forcing me to make it static?

the code is too cluttered now to give any serious feedback on it. We can't go comparing multiple snippets to try and work out how to piece them together.

I wasn't sure which was better between posting all code -where new code is mixed with old or isolate new code and post it on its own. I opted for the latter but now seems the former was better. Ideally reposting all code and highlighting new code by changing its text colour would be best. I raised this issue on CSI forum some time ago - so hopefully Khawk is doing something about that. In the mean time I will repost the code and edit this post to update

]I appreciate it's frustrating to not get help in a timely manner when we can't spend much time on our projects

In addition: :If the only way you can think of for debugging a program is "ask on a forum," then you need to learn more about various debugging techniques.
Debugging techniques may include:
- turning on all compiler warnings and paying attention to the output
- printing inputs and outputs
- stepping through code in a debugger
- using a static code analyzer and paying attention to its output
- commenting out various bits of code and verify assumptions about behavior
- copy and pasting small snippets of code to small external programs to verify behavior
- (re-)reading the documentation about the various functions used and thinking about every word in the described behavior

+1

can't help being grumpy...

Just need to let some steam out, so my head doesn't explode...

"I was forced to make 'appendToFile' static because 'main(String[] args)' is static" - This gets into basic Java programming things rather than networking, but there are several concepts tied up in this 'static' business:

  1. you have a static main() function as the entry point to your program, which is forced on you by Java;
  2. You're expected to then create objects and call methods on them, and they don't have to be static (and usually shouldn't be), and this means they can reference non-static variables that are members of that object

But more importantly, regarding "static BufferedWriter bufferedWriter" - it doesn't need to be static, and it doesn't need to be declared outside the functions at all. Your appendToFile completely overwrites whatever was stored in that variable, and then completely flushes the object at the end, so there's no need for it to exist after the function completes. So, it should be a local variable.

You might want to spend some time reading some Java fundamentals just to make sure you have all this clear in your head before proceeding. It's not directly related to your problem but you'll fix the problem more quickly when you fully understand all the code around it.

Finally fixed! But it would be a muted happy bunny this time because of the long painful time it took. But I'm still more than relieved though

It had to do a few unclosed objects in the server code and also not being closed at the right places. This might seem like "why didn't think of this before?". Well it was closing stream objects that caused the "SocketException: Connection reset by peer: socket write error" that caused me as much grieve previously. So its a delicate balance, understanding what's really going on is very crucial, so you need to close at the RIGHT place in the code on both the server and client side. Misplacing or not closing/closing too early would causing blocking, connection reset or other errors. At times it may seem logical to close an object that receives after 'writing' the received file, but then it blocks. And you remove the close() and it breaks - so what to do? Well Close after 'writing' the send bytes not after writing the received bytes

It turns out sending and receiving Jpeg files didn't pick up all the flaws in my previous code. So when I assumed "you can now send and receive .jpg files - so every thing is sorted... I should also be able to send text file with data from server to client with no problems, after all a file is a file, right?" Well except that the data didn't appear at the client received text file

So who knows, maybe when I try to move up another gear yet more flaws would be revealed.

Anyway Many thanks to Kylotan, hplus0603, Albert and satharis. All your suggestions have helped

can't help being grumpy...

Just need to let some steam out, so my head doesn't explode...

This topic is closed to new replies.

Advertisement