By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,089 Members | 2,283 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,089 IT Pros & Developers. It's quick & easy.

VB/C# - Network: Problem with socket receiving data

P: 1
Hello!

I am new to network programming, and understand just basics. Using some sample code, and having read documentation, I managed to create a simple app in C# and VB.NET. The application is supposed to do the following:
monitor ALL INCOMING TCP traffic on the local computer, and save certain parts of it as files - not log files though, but actual files that are sent to the computer as part of http or ftp. Basically if a user browse a page using a browser (any), the application will see all information that browser sees - that is all those packets containg images, html, etc., and will save the needed files (say jpg files of certain size, or whatever).

Here's my problem: it would save only 99.8% (or so) of large files (bigger than 100 KB), and not 100%. So essentialy, at this stage it is pretty much useless. I cannot understnad what is going on... my CPU usage seems to be quite low when I browse and download and when application is running - os it cannot be that it does not get enough cpu cycles to process it in time. But I don;t get where that .2% are lost. And it's not that the browser (or any other application that is using Intenet) does not receive full file - no - full files are indeed downloaded and saved, but my app seems to svae most of it, but not all.

The code is divided into two parts. I have commented it for you to understand what I mean better, so please note the comments.

1. Creating the socket, and initializing:

Expand|Select|Wrap|Line Numbers
  1.         Dim ip As String = "192.168.1.4"'my ip as determined by ipconfig - in real app fo course it will be determined by code
  2.         Dim socket As New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP)'get raw ip packets
  3.         Dim buffer As Byte() = New Byte(65536 - 1) {}'tried different sizes with ho apparent difference, at least as far as my problem is concerned
  4.         Dim pair As New SocketPair(socket, buffer)' user state object that is used to track the socket
  5.         socket.Blocking = False' tried both true and false with no differene with respect to the problem
  6.         socket.Bind(New IPEndPoint(IPAddress.Parse(ip), 0))'bind the socket to local ip on all ports - so it gets to see all incoming ip data
  7.         socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1)' this is important, so that my 2 helper classes can actually parse the raw ip packets into something useful
  8.         Dim byTrue() As Byte = New Byte() {1, 0, 0, 0}
  9.         Dim byOut(3) As Byte ' = newbyte[4];
  10.         socket.IOControl(IOControlCode.ReceiveAll, byTrue, byOut)' necessary so that the socket sees all incoming ip data
  11.         socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, AddressOf RecPac, pair)' start receiving data asynchonosly. RecPac routine will be called when data arrives
  12.  
Part 2: Process incoming data in RecPac routine:

Expand|Select|Wrap|Line Numbers
  1.     Private Sub RecPac(ByVal ar As IAsyncResult)
  2.         Dim asyncState As SocketPair = TryCast(ar.AsyncState, SocketPair)
  3.         Dim iPSocket As Socket = asyncState.IPSocket' the two line above get the socket object from the passed argument
  4.         Dim recv As Integer = iPSocket.EndReceive(ar)'get the number of bytes received. QUESTION: I am not sure if this line is the culprit, because in tehory it would stop listening at this point, and go onto processing data below, until BegineReceive is called again. So may be that's how my data is lost????
  5.         Dim d As Byte() = asyncState.Buffer'get the buffer containing the actual data
  6.         Dim iph As New IPHeader(d, recv)'initialize my helper class that would get the ip packet info, such as ip address, etc
  7.         If iph.ProtocolType = Protocol.TCP Then'we are interested in TCP only, because HTTP is based on it
  8.             Dim tcph As New TCPHeader(iph.Data, iph.MessageLength)'get the tcp header, so we can check too see needed information. Basically we need source and destination ports, as well as source ip address to determine to which file this packet belongs. And of course we need to get the data, to check for the presense of http response, and check the type of file we are getting. Basically if this is the first http response from the server for the file, then we'll see here http header, and in this case if this is the file we need, we'll create a file stream, and begin writing data to it. When the file reaches the size (the length of file stream that is becomes...) the  number specified in the "content-length" property of http response which we parsed earlier, we close the stream - we have downloaded the file.
  9. 'So basically here goes the routine that checks whether or not the packet is of interest to us, and if it is either creates a new file stream, or based on source port, destination port, and source ip, gets already created filestream from the list and writes data to it.
  10.         end if
  11.         iPSocket.BeginReceive(asyncState.Buffer, 0, asyncState.Buffer.Length, SocketFlags.None, AddressOf RecPac, asyncState)' continue receiving the data
  12.     End Sub
  13.  
As you can see it's pretty simple.
As for the two helper calsses for IPHeader and TCPHeader, I am 100% sure that they are not the case... they adhere to TCP/IP standards and parse th raw ip just fine.

Also, there is NO CONSISTENCY in the results I get - three times I would download the same file of say 10 MB, and on different times the size would be different - 9.93, 9.98, 9.85 MBs, etc. And the missing data, too would appear (or rather not appear) at different points. (I have the good version of the file, so I can compare).

Obviously, the bigger the file, the more chances, it will come out faulty.

My OS is Windows Vista Ultimate 32-bit, and I use LAN to access the Internet (I connect though DSL and via router). My download speed (peek) is 500 KB/s, so may be socket just can't cope with this.. I don't know.

I do not get any errors, btw.

I hope someone can suggest what I did wrong, as obviously I did something wrong, given that I do not have a lot of knowledge about sockets.

And also, I ma really interested in HTTP only, so if any of you know a better way fo achieving this task, please let me know. I mean I wouldn't be using all these IPHeader and TCO header classes, and then HTTP response header string parsing to get the file info, if I knew an easier - higher level way... that would instead of making me work with ip datagrams, let me work with http request and response objects - like in ASP.NET for example. The problem with that though is - I am ONLY listening and logging what other apps do... I am not makingany requests or establishing connections myslef!

I have looked into WinPCap btw, but it seems to have some compatibility issues that I cannot cope with.

Thanks.

George
Aug 9 '07 #1
Share this question for a faster answer!
Share on Google+

Post your reply

Sign in to post your reply or Sign up for a free account.