Socket ReceiveAll - c#

I am trying to capture ip packets in c#.
Everything is working fine, except that i only get outgoing packets.
My Code:
using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP))
{
sock.Bind(new IPEndPoint(MYADDRESS, 0));
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
sock.IOControl(IOControlCode.ReceiveAll, BitConverter.GetBytes(1), null);
while (true)
{
byte[] buffer = new byte[sock.ReceiveBufferSize];
int count = sock.Receive(buffer);
// ...
}
}
The problem is definitely my pc! But maybe there is a workaround ...

It is likely that that the Windows firewall is blocking incoming packets. Add your program to the firewall exclusions.

What about a different approach like using WinPcap for .Net with SharpPcap (more info)
It provides an API for capturing, injecting, analyzing and building packets using any .NET language such as C# and VB.NET
....sounds more promising

I believe the problem is that you are binding to the loopback IP, assuming that 'LOCALHOST' in your code implies 127.0.0.1. Try binding to the IP address of the interface you want to capture the packets for.
I took your code an did a quick test, and definately I see data flowing in both directions, using Windows 7. NB I am running this as Administrator, not sure how well it works otherwise.
using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP))
{
sock.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.121"), 0));
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
sock.IOControl(IOControlCode.ReceiveAll, BitConverter.GetBytes(1), null);
while (true)
{
byte[] buffer = new byte[sock.ReceiveBufferSize];
int count = sock.Receive(buffer);
IpHeader hdr = IpHeader.FromPacket(buffer, count);
if ((ProtocolType)hdr.Protocol == ProtocolType.Tcp)
{
Console.WriteLine("{0} : {1} -> {2}", (ProtocolType)hdr.Protocol, new IPAddress(hdr.SrcAddr).ToString(), new IPAddress(hdr.DestAddr).ToString());
}
}
}
IpHeader is from a library I wrote years ago, I used that to quickly decode the packets to ensure I was seeing data in both directions.
Here is a quick capture from the code above to verify (AA.BB.CC.DD is my public IP)
Tcp : 83.221.14.72 -> AA.BB.CC.DD
Tcp : AA.BB.CC.DD -> 83.221.14.72
Tcp : 83.221.14.72 -> AA.BB.CC.DD
Tcp : 83.221.14.72 -> AA.BB.CC.DD
Tcp : AA.BB.CC.DD -> 83.221.14.72
Tcp : 83.221.14.72 -> AA.BB.CC.DD
Tcp : 83.221.14.72 -> AA.BB.CC.DD
Tcp : AA.BB.CC.DD -> 83.221.14.72
Tcp : AA.BB.CC.DD -> 83.221.14.72
Tcp : AA.BB.CC.DD -> 83.221.14.72
Tcp : 83.221.14.72 -> AA.BB.CC.DD
Tcp : 83.221.14.72 -> AA.BB.CC.DD
Tcp : AA.BB.CC.DD -> 83.221.14.72

In my case I had to allow the the vshost.exe in the windows firewall

I think the problem is in the IOControl call. To be honest I don't really understand the documentation provided by MSDN about this function but there is an example in codeproject (here) about this topic, and my guess is that by passing null in the last parameter you are not getting the incoming packets.
Try this instead:
byte[] byTrue = new byte[4]{1, 0, 0, 0};
byte[] byOut = new byte[4];
sock.IOControl(IOControlCode.ReceiveAll, byTrue, byOut);

Related

UDP packets from a field device will not through azure infrastructure to my service

A field device (Loxone miniserver) is sending measurements in UDP packets to the public adress of an azure VM and to my local machine, both on port 1234(changed for integrity). On my local machine in the same network as the field device I implemented a test receiver in C# which gets the packets correctly.
On an already running application on an azure VM I added the same receiver code as in the local machine and got no UDP packets.
What I already did on the azure management platform:
- Allowed the incoming port 1234 in the network configuration
- Switched off the firewall
For testing I tried following:
- Implemented a UDP sender on the application in the azure VM which sends on broadcast-IP to port 1234 -> this works!
- Added a packet monitor to the network-interface -> here I see both packages, the internal broadcast and the field device
//Receiver-Code reduced to relevant parts
class Program{
public static void Main(string[] args){
program.Run();
}
public void Run(){
var sync = new LoxoneSyncProcess();
while(true){
sync.readUDP();
Thread.sleep(10000);
}
}
}
class LoxoneSyncProcess{
public LoxoneSyncProcess(){
private UDPSocket c = new UDPSocket();
c.Client(1234);
}
public void readUDP(){
String buffer = c.getDatBuf();
Console.WriteLine(buffer);
//process buffer
}
}
public class UDPSocket{
private Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
private const int bufSize = 8 * 1024;
private State state = new State();
private EndPoint epFrom = new IPEndPoint(IPAddress.Any, 0);
private AsyncCallback recv = null;
private String datBuf = "";
public class State
{
public byte[] buffer = new byte[bufSize];
}
public String getDatBuf()
{
String temp = datBuf;
datBuf = "";
return temp;
}
public void Client(int port)
{
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
Receive();
}
private void Receive()
{
_socket.BeginReceiveFrom(state.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv = (ar) =>
{
State so = (State)ar.AsyncState;
int bytes = _socket.EndReceiveFrom(ar, ref epFrom);
_socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv, so);
datBuf += Encoding.ASCII.GetString(so.buffer, 0, bytes);
//Console.WriteLine("RECV: {0}: {1}, {2}", epFrom.ToString(), bytes, Encoding.ASCII.GetString(so.buffer, 0, bytes));
}, state);
}
}
The code is working, I receive self sent UDP packets to port 1234 on Broadcast-IP, but not from the field device.
Are there any tables like NAT-configurations needed? Or portforewarding? Does azure support public UDP endpoints?
UDP public Endpoint is supported in Azure. Just wanted to check the size of the UDP payload that you use. If the UDP payload is > 1500 bytes then it will not work.
This is by design at the moment as we do not support fragments to public VIP endpoints right now in the vswitch. The recommendation is for customers to keep UDP datagrams to under 1500. There’s really nothing short term we could do to allow fragments through without code changes – they’re fundamentally not supported in the NAT
One thing to note is the mentioning of fragmentation according to Microsoft.
Granted the information is about TCP/IP but MTU obviously affects UDP traffic as well.
Azure and VM MTU
The default MTU for Azure VMs is 1,500 bytes. The Azure Virtual Network stack >will attempt to fragment a packet at 1,400 bytes.
Note that the Virtual Network stack isn't inherently inefficient because it >fragments packets at 1,400 bytes even though VMs have an MTU of 1,500. A >large percentage of network packets are much smaller than 1,400 or 1,500 >bytes.
Source https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-tcpip-performance-tuning

Udp server receive message from external client as if it is from server IP [duplicate]

I have an embedded Ethernet interface (Lantronix XPort) that responds to a UDP broadcast with its identifying information.
I am able to multicast the "magic packet" and datagrams are received by the listener correctly, however I also need to find out what IP Address send that response datagram. If it were TCP, I would do socket.RemoteEndPoint, but that throws an exception when applied to a UDP socket.
public class Program
{
public static void Main(string[] args)
{
// magic packet
byte[] magicPacket = new byte[4] { 0, 0, 0, 0xf6 };
// set up listener for response
Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// EDIT: Also, had to add this to for it to broadcast correctly
sendSocket.EnableBroadcast = true;
IPEndPoint listen_ep = new IPEndPoint(IPAddress.Any, 0);
sendSocket.Bind(listen_ep);
// set up broadcast message
EndPoint send_ep = new IPEndPoint(IPAddress.Parse("192.168.255.255"), 30718);
sendSocket.SendTo(magicPacket, magicPacket.Length, SocketFlags.None, send_ep);
DateTime dtStart = DateTime.Now;
while (true)
{
if (sendSocket.Available > 0)
{
byte[] data = new byte[2048];
// throws SocketException
//IPEndPoint ip = sendSocket.RemoteEndPoint as IPEndPoint;
sendSocket.Receive(data, SocketFlags.None);
if (data.Length > 4)
{
PrintDevice(data);
}
}
if (DateTime.Now > dtStart.AddSeconds(5))
{
break;
}
Console.WriteLine(".");
Thread.Sleep(100);
}
// wait for keypress to quit
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
Any thoughts? Is there a better strategy to reading the response datagrams that would let me ascertain the Remote IP Address?
EDIT:
As is typical, the minute I post on SO, a moment of clarity hits me.
Turns out I can just do this:
EndPoint remote_ep = new IPEndPoint(IPAddress.Any, 0);
// Use ReceiveFrom instead of Receieve
//sendSocket.Receive(data, SocketFlags.None);
sendSocket.ReceiveFrom(data, ref remote_ep);
And remote_ep now contains the remote endpoint information!
Take a look at ReceiveFrom instead of Receive, it will let you pass in a reference to an Endpoint.
What about Asynchronous socket?I didn't find any way to get the remote IP address. (Asynchronous method ReceiveFromAsync is my only option in wp8)
EndPoint remote_ep = new IPEndPoint(IPAddress.Any, 0); // Use ReceiveFrom instead of
sendSocket.Receive(data, SocketFlags.None);
sendSocket.ReceiveFrom(data, ref remote_ep);
i think it works for IP but it fails for port number
if you would notice
try chaging 0 to something else like 6530 4expl
it system will would generate it's random port number
Any ideas to why is it ?
P.S. Any ideas how can i change my user name here .... ?
FOUND IT : the abstract class only needed for representation of port it is in value not out
since there's no bind done before hand this operation ref EndPoint needed to represent the sender. Meaning that it is there to show senders port and IP not to specify from where to get the communication. And EndPoint instantiation is really just a formality seems like it is overriden by system with senders address anyway. I think it has to do somethign with the way UDP protocol works.
But all in all the ref EndPoint is there only shows where u got the packet from and only it does not specify where u want u'r commuicatino to be from.

Lost UDP 'connection' between client app and server app

I wrote two small applications (a client and a server) to test UDP communication and I found the 'connection' (yeah, I know, there's no real connection) between them gets lost frecuently for no reason.
I know UDP is an unreliable protocol, but the problem here does not seem the losing of packets, but the losing of the communication channel between the apps.
Here's client app code:
class ClientProgram
{
static void Main(string[] args)
{
var localEP = new IPEndPoint(GetIPAddress(), 0);
Socket sck = new UdpClient(localEP).Client;
sck.Connect(new IPEndPoint(IPAddress.Parse("[SERVER_IP_ADDRESS]"), 10005));
Console.WriteLine("Press any key to request a connection to the server.");
Console.ReadLine();
// This signals the server this clients wishes to receive data
SendData(sck);
while (true)
{
ReceiveData(sck);
}
}
private static void ReceiveData(Socket sck)
{
byte[] buff = new byte[8];
int cnt = sck.Receive(buff);
long ticks = BitConverter.ToInt64(buff, 0);
Console.WriteLine(cnt + " bytes received: " + new DateTime(ticks).TimeOfDay.ToString());
}
private static void SendData(Socket sck)
{
// Just some random data
sck.Send(new byte[] { 99, 99, 99, 99 });
}
private static IPAddress GetIPAddress()
{
IPHostEntry he = Dns.GetHostEntry(Dns.GetHostName());
if (he.AddressList.Length == 0)
return null;
return he.AddressList
.Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !IPAddress.IsLoopback(ip))
.FirstOrDefault();
}
}
Here's the server app code:
class ServerProgram
{
private static int SLEEP = 5;
static void Main(string[] args)
{
// This is a static IP address
var localEP = new IPEndPoint(GetIPAddress(), 10005);
Socket sck = new UdpClient(localEP).Client;
// When this methods returs, a client is ready to receive data
var remoteEP = ReceiveData(sck);
sck.Connect(remoteEP);
while (true)
{
SendData(sck);
System.Threading.Thread.Sleep( ServerProgram.SLEEP * 1000);
}
}
private static EndPoint ReceiveData(Socket sck)
{
byte[] buff = new byte[8];
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int cnt = sck.ReceiveFrom(buff, ref clientEP);
Console.WriteLine(cnt + " bytes received from " + clientEP.ToString());
return (IPEndPoint)clientEP;
}
private static void SendData(Socket sck)
{
DateTime n = DateTime.Now;
byte[] b = BitConverter.GetBytes(n.Ticks);
Console.WriteLine("Sending " + b.Length + " bytes : " + n.TimeOfDay.ToString());
sck.Send(b);
}
private static IPAddress GetIPAddress()
{
// Same as client app...
}
}
(this is just test code, don't pay attention to the infinite loops or lack of data validation)
The problem is after a few messages sent, the client stops receiving them. The server keeps sending, but the client gets stuck at sck.Receive(buff). If I change SLEEP constant to a value higher than 5, the 'connection' gets lost after 3 or 4 messages most of the time.
I can confirm the client machine doesn´t receive any packet when the connection is lost since I use Wireshark to monitor the communication.
The server app runs on a server with direct connection to Internet, but the client is a machine in a local network, behind a router. None of them has a firewall running.
Does anyone have a clue what could be happening here?
Thank you!
EDIT - Additional data:
I tested the client app in several machines in the same network and the connection get lost always. I also tested the client app in other network behind other router and there is no problem there. My router is a Linksys RV042 and never had any problem with it, in fact, this app is the only one with problems.
PROBLEM SOLVED - SHORT ANSWER: It was a hardware problem.
I don't see any overt problems in the source code. If it is true that:
The server keeps sending packets (confirmed by WireShark on the server)
The client never receives the packets (confirmed by WireShark on the client)
..then the problem could be related to networking equipment between the two machines, which don't always handle UDP flows as expected especially when behind routers/firewalls.
I would recommend the following approach to troubleshooting:
Run client & server on the same system and use the loopback interface (confirm UDP code works on the loopback)
Run the client & server on two different systems that are plugged into the same Ethernet switch (confirm that UDP communication works switch-local)
If everything works switch-local you can be fairly sure you have a network configuration problem.

UDP transmission over WAN

I have asked a couple of similar questions the last couple of days and received some really great help. I now understand my problem quite a bit better but I appear to have hit a snag. I have written a client server application that uses both a TCP and UDP connection. The TCP connection works fine over both LAN and WAN but the UDP connection fails over WAN. Based on the questions I asked previously I realized that my server needed to reply to the client at the EndPoint from which it received a communication. I set everything up to work that way. I will post code after the question. My problem is now that while I am using the EndPoint from the client connection and the client is establishing connection first I am still unable to make the UDP connection. It appeared to work over one network but then failed over all the others I have tried. Any help on figuring this out is appreciated. Here is the code.
Receive UDP Messages on the server
private void receiveUDP()
{
System.Net.IPEndPoint test = new System.Net.IPEndPoint(System.Net.IPAddress.Any,UDP_PORT);
System.Net.EndPoint serverIP = (System.Net.EndPoint)test;
trans.Bind(serverIP);
System.Net.IPEndPoint ipep = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
System.Net.EndPoint Remote = (System.Net.EndPoint)ipep;
while (true)
{
byte[] content = new byte[1024];
int recv = trans.ReceiveFrom(content,ref Remote);
int portNum = ((System.Net.IPEndPoint)Remote).Port;
string message = Encoding.ASCII.GetString(content);
string[] data = message.Split((char)124);
//UpdateStatus(data[0] + data[1]);
UserConnection sender = (UserConnection)clients[data[0]];
if (sender.PortNumber != portNum)
sender.PortNumber = portNum;
if (sender.RemoteEnd != Remote)
{
sender.RemoteEnd = Remote;//Stores the EndPoint from the client connection
}
if (data.Length > 2)
{
OnLineRecieved(sender, data[1] + "|" + data[2]);
}
else
{
OnLineRecieved(sender, data[1]);
}
}
}
Client Listens here
private void receiveUDP()
{
System.Net.IPEndPoint test = new System.Net.IPEndPoint(System.Net.IPAddress.Any,UDP_PORT_NUMBER);
System.Net.EndPoint serverIP = (System.Net.EndPoint)test;
server.Bind(serverIP);
server.Ttl = 50;
EndPoint RemoteServ = (EndPoint)servIP;
while (true)
{
byte[] content = new byte[1024];
int data = server.ReceiveFrom(content, ref RemoteServ);
string message = Encoding.ASCII.GetString(content);
result = message;
ProcessCommands(message);
}
}
EDIT: SERVER'S Sending function
public void SendData(string data)
{
if (RemoteEnd != null)//RemoteEnd is refreshed every time the client sends a UDP message
//Each Clients RemoteEnd is stored in a collection of Client objects in a server hashtable
{
//ipep = new IPEndPoint(ipAdd, PortNumber);
byte[] dataArr = Encoding.ASCII.GetBytes(data);
trans.SendTo(dataArr, dataArr.Length, SocketFlags.None, RemoteEnd);
}
}
There could be a lot of things wrong. Remember, UDP doesn't provide transmit pacing, retransmissions, or acknowledgements. So if you need them, you must provide them. If you have the client send first and then wait for responses to each query, your first lost packet will kill the connection.
You also kind of forgot to describe the problem. You say you fail to make the connection, but what does that mean? Does the server receive the client's first packet or not? Does the client receive the server's first reply or not?
You have to determine if this is a programming problem or a network configuration problem.
what I would do is run the client app on the server machine and the server app on the client machine (and switch the hosts they connect to).
If the server app no longer receives UDP messages from the client app, then you have a networking configuration problem.
If the server app can still receive messages from the client app, then you have a programming problem.

TcpConnection capable of handling concurrent requests. Client-Server

I'm trying to build a simple Client-Server Application with the following codes:
//SERVER
IPAddress ipAd = IPAddress.Parse("192.163.10.101");
TcpListener myList = new TcpListener(ipAd, 8001);
myList.Start();
Console.WriteLine("The server is running at port 8001...");
Console.WriteLine("The local End point is :" + myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
//CLIENT
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("192.163.10.101",8001);
Console.WriteLine("Connected");
this actually does what I need wherein the client can connect to the server. However, when I try to run multiple instances of the client to connect with the server, the server only accepts the first client to connect. Meaning there's like a one-to-one connection wherein only one client can connect with the client. However, what I need is to give the server the ability to accept connections from more than one client.
If anyone can point me a possible solution to this, I'll really be appreciative! Thanks!
You need to call AcceptSocket again to accept another socket.
A typical design would be to have to call BeginAcceptSocket and in the callback call EndAcceptSocket, dispatch the client processing to its own thread (or a worker thread using async methods) and then call BeginAcceptSocket again.
This fragment is untested but should be more or less right/ get you thinking in the right direction.
class Server
{
public Server()
{
TcpListener listener = null;
// init the listener
listener.BeginAcceptSocket((ar) => AcceptLoop(ar, listener),null);
}
public void HandleClientSocketRead(IAsyncResult ar, byte[] recvBuffer, Socket clientSocket)
{
int recvd = clientSocket.EndReceive(ar);
//do something with the data
clientSocket.BeginReceive(recvBuffer, 0, 1024, SocketFlags.None, (ar2) => HandleClientSocketRead(ar2, recvBuffer, clientSocket), null);
}
public void AcceptLoop(IAsyncResult ar, TcpListener listener)
{
Socket clientSocket = listener.EndAcceptSocket(ar); // note that this can throw
byte[] recvBuffer = new byte[1024];
clientSocket.BeginReceive(recvBuffer, 0, 1024, SocketFlags.None, (ar2) => HandleClientSocketRead(ar2, recvBuffer, clientSocket), null);
listener.BeginAcceptSocket((ar) => AcceptLoop(ar, listener), null);
}
}
If you are looking to write a server, a good design is to have a [server].exe and a [client].exe. The [server].exe, will of course accept and process all incoming connections, maintain the client sockets, and perform whatever actions you need. Below is a very basic example on writing a server to accept multiple client sockets, and store them in a List object. This, however, is not multithreaded so the code, does block.
[server].exe
//-----------------------------------------------------------------------------
// <copyright file="Program.cs" company="DCOM Productions">
// Copyright (c) DCOM Productions. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------
namespace MultiSocketServerExample {
using System;
using System.Net.Sockets;
using System.Net;
using System.Collections.Generic;
class Program {
static List<Socket> m_ConnectedClients = new List<Socket>();
static void Main(string[] args) {
Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
host.Bind(new IPEndPoint(IPAddress.Any, 9999));
host.Listen(1);
while (true) {
m_ConnectedClients.Add(host.Accept());
Console.WriteLine("A client connected.");
}
}
}
}
Then to work with your clients: (Again, very basic example)
m_ConnectedClients[0].Send(Encoding.ASCII.GetBytes("hello!");
Network programming with the Socket class is a lot easier in my opinion then using TcpListener and TcpClient. The reason I say this is that it is already a really good and easy to use implementation, and by using TcpListener and TcpClient where they create further abstraction, lessenes your ability to understand what is going on (in my opinion).

Categories

Resources