Solved

Best way to use Sockets in C#

Posted on 2012-03-19
16
724 Views
Last Modified: 2013-12-03
I have seen a lot of ways to deal with sockets in VB.NET, however I am not sure which way is the best way that allow:
1. Sending string data (both sides)
2. Sending binary data (both sides, including large binary data and files)

Important: I DONT want to know how to use Sockets, I already know that.

I want the best way to use to achieve what I said above.

Basically I want the following methods to be included:
sendData();
sendFile();

I want to be using TcpListener/TcpClient.

The problem I usually face is when I have 1025 bytes buffer and I receive for example two binary buffers, one use the full 1025 and the other use for example 400 bytes from 1024, so if i wrote that to a file it will write about 2050 which is invalid file size, the file size is only 1425 bytes.
0
Comment
Question by:Mohamed Abowarda
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
  • +2
16 Comments
 
LVL 20

Expert Comment

by:BuggyCoder
ID: 37737757
make your methods look like this on receiving end:-
public void ReceiveData(byte[] arrBytes);
public void ReceiveFile(FileStream stream);

Open in new window

0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 37737775
@BuggyCoder: Can you give an example or sample code? Usually I receive the data in bytes and converting bytes to FileStream, I think it will keep unnecessary data at the end.

Another thing is sending Binary data, could be 10 MB of binary data but its NOT a file.

Thanks,
0
 
LVL 20

Expert Comment

by:BuggyCoder
ID: 37737796
even in case of file as well, just use the first method.
Just make sure that on the other end send your file as stream of bytes....

here is a link to convert filestream to byte array:-
http://msdn.microsoft.com/en-us/library/system.io.filestream.read.aspx
0
Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

 
LVL 83

Expert Comment

by:CodeCruiser
ID: 37740117
>The problem I usually face is when I have 1025 bytes buffer and I receive for example two binary buffers, one use the full 1025 and the other use for example 400 bytes from 1024, so if i wrote that to a file it will write about 2050 which is invalid file size, the file size is only 1425 bytes.


Have you tried using the stream.length property to determine the size of data instead of using 1024 bytes?


http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 37740481
@CodeCruiser: I am not sure where to use stream.

I want someone to modify the following code to solve the problem (please see the comments in the code):

// Public Declaration
bytes[] buff = new bytes[1024];

// This line is used after connection
tcpClient.Client.BeginReceive(buff, 0, buff.Length, SocketFlags.None, DataReceived, null);

void DataReceived()
{
      // Here you can process the buffer you have received...
      // EXAMPLE: string str = Encoding.ASCII.GetString(buff);
      // The problem I usually get here because buff contains 1025 bytes of data EVEN if the server sent only 50 bytes.

      // Receive more data
      tcpClient.Client.BeginReceive(buff, 0, buff.Length, SocketFlags.None, DataReceived, null);
}

Open in new window

0
 
LVL 83

Accepted Solution

by:
CodeCruiser earned 300 total points
ID: 37774319
The EndReceive method returns an integer which is the number of bytes received so you can use that to determine how many bytes out of 1024 to write to the file.
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 37835805
@CodeCruiser: Can you please update the sample code that I posted earlier.

Thanks,
0
 
LVL 83

Expert Comment

by:CodeCruiser
ID: 37853650
Where is your endreceive code?
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 37854070
I am not using endreceive code yet, the code I am using is similar to the one I posted earlier:
// Public Declaration
bytes[] buff = new bytes[1024];

// This line is used after connection
tcpClient.Client.BeginReceive(buff, 0, buff.Length, SocketFlags.None, DataReceived, null);

void DataReceived()
{
      // Here you can process the buffer you have received...
      // EXAMPLE: string str = Encoding.ASCII.GetString(buff);
      // The problem I usually get here because buff contains 1025 bytes of data EVEN if the server sent only 50 bytes.

      // Receive more data
      tcpClient.Client.BeginReceive(buff, 0, buff.Length, SocketFlags.None, DataReceived, null);
}

Open in new window


I only need to update that code to get the result I asked for.

Thanks,
0
 
LVL 16

Assisted Solution

by:hjgode
hjgode earned 200 total points
ID: 37934686
Hello

you have use EndReceive and the integer that returns the number of bytes received or you will nit know, how many bytes have been read in reality.

Using buffers to read an unknown number bytes is done normally in chunks of a given size and using the number of bytes read returned by a read. So, you have a buffer of 1024 bytes and start reading. Every read has to be checked for the number of bytes read. Possibly, the number of bytes read is only 500. Then you have to stop reading and use only the first 500 bytes of your buffer. If the number of bytes read is equal the buffers ize, you have to do additional reads until the number of read bytes is less then your buffer.

~josef
0
 
LVL 34

Expert Comment

by:sarabande
ID: 37937759
for variable sized data via sockets you normally would pass a fixed-sized "header" prior to the data. the header contains (at least) the length of the data in bytes as first information. often you also would add sender information or some type of message and put them all to a  structure. the structure must have same alignment and size on all platforms (simply use 32-bit integer type for all members). then your receive function firstly would read until the full header was read. if sender and receiver could be on different endian platforms the sender would convert all integer members to "network order" what is big-endian. there are platform-specific functions htons (for 16-bit integer) and htonl (32-bit) which do that job. after you received the full header you would reconvert the integer length by calling ntohl. after you know the length of the data stream you could allocate an appropriate buffer and read in a loop until error or until all data was received.

Sara
0
 
LVL 16

Expert Comment

by:hjgode
ID: 37938204
Hi

I aggree to the way sarabande describes a bniary socket transfer. It is also a good idea, to describe the length of the data first and possibly to add some CRC or similar error checking.

That leads to your first question, if it is better to use strings or bytes to transfer data via sockets. If you go with strings, you may have to control the way unicode or UTF8 strings are converted to/from byte arrays, as finally, sockets only transfer bytes. You have also to consider, how the end of a string is marked (normally with one or two (unicode) null byte(s)). Or you add some marker to the end like "<EOT>".

But finally, you end up with reading bytes in chunks until all bytes are read. You have to re-assemble the bytes back to a large array or a string.

~josef
0
 
LVL 12

Author Closing Comment

by:Mohamed Abowarda
ID: 38025212
I have been busy with other projects in other programming languages, so I didn't get a chance to even try the solution here, using EndReceive() works perfectly!

Thanks,
0

Featured Post

Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
DataMember property 'tablename' cannot be found on the DataSource. 4 52
Header Font Size in Grid View 6 27
VB.net/VSTO Excel Add-in 2 19
VB.Net Data Class 1 25
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question