I'm using UdpClient to send a message and listen for a response, like this:
Client = gcnew UdpClient();
HostEndPoint = gcnew IPEndPoint(192.168.0.20, 52381);
Client->Connect(HostEndPoint);
Client->Send(Message, Message->Length);
Bytes = Client->Receive(HostEndPoint);
I have two similar devices but they respond differently. In the first case, the destination responds on the same port as I send to. So, for example, sending with a random source port of 49542, this happens:
Request: 192.168.1.10:49542 > 192.168.1.20:52381
Response: 192.168.1.20:52381 > 192.168.1.10:49542
And with the above code I get the response as expected.
The other similar device however responds with a random port (which changes whenever it is powercycled), like this:
Request: 192.168.1.10:49542 > 192.168.1.20:52381
Response: 192.168.1.20:46468 > 192.168.1.10:49542
And in this case, I do not receive the response, Receive() will timeout. I believe I understand why there's nothing received. There's suggestion in .net docs that once you use a IPEndPoint with UdpClient() or Connect(), any other responses are filtered out. So, I'm not even sure why Receive has an IPEndPoint parameter.
I have monitored the communication with WireShark and I can see the messages in both directions. So I know the device is responding I just can't figure out how to receive it in my code.
The best solution I think is to be able to receive any response that arrives to my source random port (49542 above), additionally to specify the destination IP as well, but that may not be needed. Alternatively, to listen for any response from the destination IP, on any port, since I don't see how to know what port the device is responding with.
As best as I can figure out you have to indicate a port # for Receive(IPEndPoint), which usually is the destination port of the message you sent to in the first place - as it is in my code sample (which works with the first device). The random port chosen by Connect can't be listened to, that's the receiving port, but I think Receive listens for the sending port from the device. which is unknown.
I tend to think that the fact that I can't find any information about how this can be done suggests that it can't be done because devices aren't supposed to respond from a random port. But, I've discussed this issue with the manufacturer and they insist it's correct behavior.
Also note, I've tried to create a second UdpClient to listen for the response from the destination IP, but it also requires a port be defined, and there's no way I can tell to know what port to listen for. I have tried UdpClient()->Client->RemoteEndPoint, but I'm pretty sure, this is the endpoint I'm starting with which has the known port, not the random port.
This is the first time I've encountered this and it seems weird to me. The devices are from a major manufacturer though, that surely knows what they're doing.
I believe I have solved this. The trick is to not use Connect, but instead to pass HostEndPoint in the Send command. This approach works with both devices.
Client = gcnew UdpClient();
HostEndPoint = gcnew IPEndPoint(192.168.0.20, 52381);
// Client->Connect(HostEndPoint);
Client->Send(Message, Message->Length, HostEndPoint);
Bytes = Client->Receieve(HostEndPoint);
Although it's working, I'm not completely sure what messages it will allow thru. It might allow any port from the specified IP, or it might allow any response from the specified IP that is directed to the initial random source port. I'm not sure.
Also, I initially thought I might have to set HostEndPoint->Port = 0 between Send and Receive. That works, but it isn't necessary.
Related
I'm writing a server for a biometric fingerprint device that connects via GPRS. The server receives GET and POST requests from the device and then will perform the required actions.
With the POST requests, the device should attach some additional data to the request.
The problem is, when I connect the device to the server via LAN, all the data comes through fine. When I connect via GPRS, the request body doesn't get picked up by my server.
On the left, is when I connect via LAN...the body of the message is attached. On the right, is via GPRS, everything remains the same, however, there is no body.
I ran Wireshark over the LAN and the GPRS connections. The packets, when I drill down, all have the body attached but on Wireshark, over GPRS, I get messages like above - with the out of order and RST, ACK and sometime PSH, ACK.
Contrasted with the LAN packets, which have none of these problems.
This is the code I'm using to read from the TCPListener
try
{
if (tcp == null)
{
this.tcp = new TcpListener(IPAddress.Parse(serverIP), port);
}
this.tcp.Start();
listening = true;
while (listening)
{
Socket mySocket = null;
// Blocks until a client has connected to the server
try
{
mySocket = this.tcp.AcceptSocket();
Thread.Sleep(500);
byte[] bReceive = new byte[1024 * 1024 * 2];
mySocket.Receive(bReceive);
Analysis(bReceive, mySocket);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
this.tcp.Stop();
This is the original code I got from their developer. I've tried various combinations of async, TcpClient and different socket options such as KeepAlive and DontLinger, but none seem to cure this problem.
Other than manually capturing the packets in C# to get the body, are there any C# classes I can use to read the entire request?
TCP is a stream oriented protocol. Everybody knows that but a lot of developers do not consider that when they implement a TCP receiver.
When a send calls Send("ABCDEFG") and client calls Receive(buffer) the buffer may contain "ABCDEFG" or "ABCD" or "A" or whatever substring from original data that begins with "A". TCP is a stream of data without any information about message boundaries.
The receiver that needs to receive a message with a length that is unknown during the compile time (like an HTTP request) must contain a logic that receives the header, parse it and than waits till complete message is received.
But you don't need to implement it yourself. C# has the class HttpServer that already contains this logic. Moreover there are libraries with REST support. It is reinventing wheel to implement a REST server and start with TcpListener and sockets.
I ended up implementing the server as async using the code in the link below. This is so I could implement the logic to reread the stream if the end of the stream hasn't been reached. I just had to change the end of file condition for my circumstances.
Here's a link to the article:
https://learn.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example
Good day all
Info:
Topic: Multicast
First off, I have found the solution but I do not understand why this is the solution.
**Scope : ** (removing any cluttering/unnecessary code)
new_socket()
{
//SND_LOCAL_IP = 10.0.0.30 - local network adapter's IP
//SND_MCAST_PORT = 80 port used to broadcast Multicast Packets
//_SND_LOCAL_EP = new IPEndPoint(SND_LOCAL_IP, SND_MCAST_PORT); <problem>
_SND_LOCAL_EP = new IPEndPoint(SND_LOCAL_IP, 0); <fixed>
}
init_socket()
{
_SND_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_SND_Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_SND_MCAST_IP, _SND_LOCAL_IP));
_SND_Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
_SND_Socket.ExclusiveAddressUse = false;
_SND_Socket.Bind(_SND_LOCAL_EP); <<< ====== PROBLEM LINE=====
}
The problem:
My listener runs on a Thread seperately, on a form_load event, thus it initializes in the same way as my SND_Socket does, however changing the SND_Socket.Bind() port to 0 allows me to recieve these Multicast packets.
As by the def MSDN, adding the ExclusiveAddress should not alleviate this problem (since the recieve and send sockets are initialized in the same way).
true if the Socket allows only one socket to bind to a specific port; otherwise, false. The default is true for Windows Server 2003 and Windows XP Service Pack 2, and false for all other versions.
and further on, in Remarks this is confirmed:
If ExclusiveAddressUse is false, multiple sockets can use the Bind method to bind to a specific port; however only one of the sockets can perform operations on the network traffic sent to the port. If more than one socket attempts to use the Bind(EndPoint) method to bind to a particular port, then the one with the more specific IP address will handle the network traffic sent to that port.
If ExclusiveAddressUse is true, the first use of the Bind method to attempt to bind to a particular port, regardless of Internet Protocol (IP) address, will succeed; all subsequent uses of the Bind method to attempt to bind to that port will fail until the original bound socket is destroyed.
This property must be set before Bind is called; otherwise an InvalidOperationException will be thrown.
Why does the
Socket.ExclusiveAddress = false
not allow the SND_Socket to listen on this IP and port as "Listener_Socket", furthermore why does setting port to 0 in the RCV_Socket.Bind() solve this problem?
Without a good Minimal, Complete, and Verifiable Example it's impossible to know for sure what problem you're even having specifically, never mind know for sure what the cause would be. Lacking that, some observations/comments related to the question as stated:
The ExclusiveAddressUse property affects not the socket on which it's set, but any other socket bound after that socket. It prevents any other socket from using the same port number, i.e. which it would otherwise be able to do through the ReuseAddress socket option.
The ReuseAddress socket option does affect the socket on which it's set. It's what allows a socket to bind to the same port that some other socket on the same adapter had already been bound.
One would typically not use both of those options at the same time. Either you want the sockets to cooperate, where one allows the other to reuse the same port number, or you want to prohibit any other socket from using the same port number.
Binding to port 0 can in some cases alleviate issues that might otherwise occur when misusing the address-exclusivity options. With the incomplete question, I cannot infer what specific problem you are having. But binding to port 0 causes the socket to select a unique port number, which will of course avoid any problems with port number conflicts.
Other than that, the biggest issue I see in your code is that you are attempting to join the multicast group before you call Bind(). You should be doing it the other way around, i.e. bind the socket, and then join the multicast group.
Most likely, you should not be using ReuseAddress at all. Your sockets should have unique port numbers. You may use ExclusiveAddressUse, as a preventative measure to ensure you get an exception if some code does try to bind a socket to a port that's already in use.
I recommend that you start by closely following the example found on MSDN on the documentation page for the MulticastOption Class. Once you have a working example using that code, then you can adjust the code to suit your specific needs.
My situation: I have an xspeech for voip, when there is an action about phone, the messages(packets) are sent to the xspeech interface. And from this interface the logs of these action are sent to specific IP address which is my IP address. And also these logs are sent from a specific port.
I am trying to develop an application that reads these logs(not a file). I tried TCPListener and TCPClient, they worked but not in my situation. I thought these logs are not sent from TCP port. This is the problem.
From your post I suspect it is using UDP... this would mean that you need to use UDPClient class to receive and process...
Depending on whether they offer a TAPI provider you can use:
http://www.codeproject.com/KB/IP/devangpro.aspx
http://www.codeproject.com/KB/dotnet/CShart_TAPI_3x.aspx
http://www.codeproject.com/KB/IP/Video_Voice_Conferencing.aspx
http://msdn.microsoft.com/en-us/library/ms734214.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms734257%28v=vs.85%29.aspx
It may be necessary to build a SIP proxy (this would be able to generate for example "Pickup event"):
http://www.codeproject.com/KB/cs/SIP_stack_with_SIP_proxy.aspx
http://sipsorcery.codeplex.com/
http://www.independentsoft.de/sip/index.html
http://www.konnetic.com/products/products_sip_sdk_std.aspx
http://www.voiceelements.com/Products/VEToolkit.aspx
EDIT - as per comments other possibilities:
If what you try to catch is sent as syslog message then see http://michael.chanceyjr.com/useful-code/syslogd-class-for-sending-and-receiving-syslogd-events/ .
Another possibility is SNMP - for this see http://www.snmpsharpnet.com/
SIP uses UDP per default.
It's not as simple as being able to take packets from one endpoint, log them and then send them to the real destination. You'll break things like NAT handling if you do so.
You need to act as a full SIP proxy (stateful) or as a B2BUA.
The easier way is to download an existing sip-proxy and just make it log to a file and read that file.
If you're recieving the information on at your IP address then I too would have thought that TCP/IP was being used. Have you checked that your firewall isn't blovking the port in question.
I would suggest that you have another look at what protocol is being used (it may be UDP) and use the Socket class instead.
I've a plugin which always listening to the port 6002, and i have an ASP.net application which sending messages to the same port and receiving the reply from the plugin on the same port,
Sending is working fine, and the plugin sends a reply on the same port but i don't know how to catch this reply, when i try to listen to the same port using Tcplistener the start method throws this exception : Only one usage of each socket address (protocol/network address/port) is normally permitted,
is there any way to catch the received message
Thanks
It sounds like you are wrongly assuming that the Socket which you get from TcpListener.AcceptSocket can only be used in one direction.
Sockets can actually be bidirectional. You can use Send to send something, and Receive to listen for get the replies. Open one socket, and then use it for both sending and receiving.
In short, no.
Once a port is opened an exception will be thrown if further attempts are made to utilise that same port from a different source - as you are experiencing right now. There isn't a way to get around this.
I've solved this problem using this way ,, I know it's old method but it's working !! :
'/*Variables Initialization*/
dim objSocket, strServicePort, strIpAddr, strResult, strMsgTo, strMsgResponse
strServicePort = "6002"
strIpAddr = "127.0.0.1"
'/* Create a TCP/IP socket. */
objSocket = Server.CreateObject("Intrafoundation.TCPClient.3")
objSocket.ClearLog()
'/* Establish socket connection. */
objSocket.Open (strIpAddr,strServicePort)
objSocket.Timeout=60.0
strMsgTo ="---- Message here ----"
'/* Send request message to plugin */
objSocket.SendRN(strMsgTo)
'/* receive XML Request Message from plugin */
strMsgResponse = objSocket.Recv()
strMsgResponse = Replace(strMsgResponse, vbLf, "")
objSocket.Close()
If you want to inspect traffic you can use winpcap.
edit: I don't think you are asking the right question. In this case the plugin is the server (listening on port 6002) and your ASP.net app is the client listening on some arbitrary port. You only need to bind to a different port in your ASP.net app if it also needs to run as a server with the plugin acting s the client. In this case you should pick a different port even though there are, in fact, ways to make it work when they are both bound to the same port.
In your case though you should just read back responses from the connection you established from the client.
I've got a strange problem. I have a client sending packets to my server, but my servers UDP socket never receives them. Same thing happens the other way around, if I send and he tries to receive.
Check this image, captured from wireshark:
http://img263.imageshack.us/img263/2636/bokus.png
I hav bound my UDP socket to EndPoint 192.168.2.3, which is the internal IP of the server, and port 9998.
The client sends data to my IP, which should then be forwarded to the local server machine..
As you can see wireshark clearly detects incomming packets for 192.168.2.3 with destination port 9998 but nothing gets delivered!
(...why does it say distinct32 btw in destination port?)
Something else to watch for is make sure any firewall you might running has a rule setup to allow communications on your port 9998.
If I had to guess (would need to see your recieving C# code to know), It looks like you might be trying to receive UDP packets but using TCP protocol on the client side. (Or i might just be misunderstanding some of the text of your screenshot.)
Theres no need to 'listen' for a connection when using UDP. UDP packets don't have a connect/disconnect protocol. Nor do they guarantee that packets are received in the same order they're sent.
try using something along these lines in your C# client and see if you get data.
var udpClient = new System.Net.Sockets.UdpClient(9998);
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);