I'm trying to connect to an UAP Server (used for sending and receiving USSD messages in Huawei) using Socket class but there's a problem while receiving data from server. I can connect to server correctly and also I can send data to server but I have problem with receiving data.
This is my code for connecting and sending message:
IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); //server
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 2020);
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(remoteEP);
//bind to socket, here I send bind message
Bind();
and inside the Bind function, I call receive method to get data from server:
private static void receive()
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = clientSocket;
// Begin receiving the data from the remote device.
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(receiveCallback), state);
}
catch (Exception ex)
{
Console.WriteLine("receive | " + ex.ToString());
}
}//receive
Here you can see my Wireshark log while connecting, sending data and receiving data from server:
But as you can see, last two messages from server are highlighted with red color which means there's a problem with receiving data from server. Also I don't see data field in details:
I really don't know what's the problem, is this a problem with server or not? Should I use another Socket client to connect and receive data from server or not?
TCP reset packets aren't a part of your application level protocol and your application shouldn't be expected to see them.
Exactly what is the incorrect behavior with your application, because with what you've posted, I'm not seeing any problems.
Related
I have a UDP Socket connection working between devices with local IPs (192.168.x.x), that I want to switch to a connection with an external server, with the following configuration:
Create socket
private Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
private const int bufSize = 4096 * 4;
private State state = new State();
private EndPoint epFrom = new IPEndPoint(IPAddress.Any, 0);
private AsyncCallback recv = null;
private static int PORT = 27000;
Openning device as a server to listen through the socket
_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
_socket.Bind(new IPEndPoint(IPAddress.Any, port));
Receive(); // Function to receive datagrams through the socket, irrelevant to this issue
Connect socket to remote endpoint
// {address:port} of an external server
_socket.Connect(new IPEndPoint(IPAddress.Parse(address), port));
Send data to socket
_socket.BeginSend(data, 0, data.Length, SocketFlags.None, (ar) =>
{
try
{
_socket.EndSend(ar);
}
catch (Exception ex)
{
Console.WriteLine("[UDP] Error Send: " + ex.ToString());
}
}, state);
The code above works fine for local IP addresses, the problem came when trying to use as a remote ip endpoint a public IP of a remote server.
The datagram seemed to be sent but it never arrived to the server. I tried to connect the phone to a VPN and the local IP changed from a 192.168.x.x to a 10.0.x.x, and then the connection to the external server worked.
Therefore, connection with an external IP only worked when the device's IP was a private IP of class A, but it didn't work with a class C range (https://www.meridianoutpost.com/resources/articles/IP-classes.php).
I want to find a solution to be able to connect to external IP address without having to connect a third party VPN software.
If someone has the same question, I have already solved it.
To access external IPs with local class C IPs and no VPN you should do UDP hole punching instead of trying to establish a connection.
Erase the .Connect() and the .Bind() methods, and, instead of using BeginSend/EndSend, use the SendTo or SendToAsync methods with the server's public IP as the endpoint destination.
Additionally, I recommend changing:
SocketOptionName.ReuseAddress
to:
SocketOptionName.PacketInformation
I am having some trouble with some bi-directional socket code I wrote. I am connecting to a server like this:
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_clientSocket.BeginConnect(new IPEndPoint(IPAddress.Parse("100.100.100.1"), 8677), new AsyncCallback(ConnectCallback), null);
_buffer = new byte[_clientSocket.ReceiveBufferSize];
Then in the callback I'm doing this:
private void ConnectCallback(IAsyncResult AR)
{
_clientSocket.EndConnect(AR);
byte[] buffer = Encoding.ASCII.GetBytes("CONNECT");
_clientSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(SendCallback), null);
}
I also need to receive data from the server, but I'm unclear on how to get the socket of the server during this process. I wrote some BeginReceive logic, but I'm consistently getting errors that I'm using the wrong socket.
It seems like somewhere in my above code I should be able to get the socket similar to how I'm doing it in my server's BeginAccept callback code:
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket);
then in AcceptCallback:
Socket server = (Socket)AR.AsyncState;
Socket client = server.EndAccept(AR);
It seems obvious to me that I'm just missing a step or concept to get me past this. I've done countless searches, but either I'm searching for the wrong thing or it's just not out there.
No, you actually don't need server side socket. You should use your client socket.
After connecting is completed, you can call _clientSocket.BeginReceive(). For example, in ConnectCallback method, as you did with BeginSend.
If you are getting exception with that, please add exact code you are using and exception you are getting.
I've got a little problem with the .Net Sockets in C#.
I programmed a client and a server working with TCP.
As the client is opened it sends a handshake to the server. The server answers with it's state (clientexists, clientaccepted,...). After that the application sends a getdata-request, abandons the connection and listens for the server's 'response'. Now, the server builds a connection to the client and sends all the data the client needs.
The code and everything else works, but the problem:
On our company testserver it works fine, on the live server only the handshake works. After it the client doesn't receive any more data. Serverapplication is the same on both servers.
I thought the problem was caused by some firewall (server wants to build a tcp connection to the client -> not good), but the system administrator said there is no firewall that could block that.
Now I'm searching for a ('cheap') solution that doesn't take too much time and changes in code. If anyone knows how to theoretically solve that, that would be great.
BTW: I am not allowed to do anything on the live server other than run the serverapplication. I don't have the possibility to debug on this server.
I can't publish all of my code, but if you need to see specific parts of it, ask for it please.
---EDIT---
Client-Server communication
1) Client startup
Client send handshake (new tcp connection)
2) Server validates handshake and saves IP
Server responds with it's client state (same tcp connection)
3) Client acknowledges this response and abandons this connection
Client sends getdata-request (new tcp connection)
Client abandons this tcp connection, too
4) Server receives getdata-request and collects the needed data in the main database
Server sends all the collected data to the client (multiple tcp connections)
5) Client receives all data and displays it in it's GUI (multiple tcp connections and the order of the data is kept by working with AutoResetEvents and Counts of sockets to send)
This is the main part my code does. It's by far not the best but it was for me as I wrote it I guess. Step one, two and three work as intended. The processing of the data works fine, too.
Another thing i forgot to mention is that the solution uses two Ports '16777' and '16778'. One to receive/listen and one to send.
My code is based on the MSDN example of the asynchronous server and client.
Sending a handshake (and getdata-request)
public void BeginSend(String data)
{
try
{
StateObject state = new StateObject();
state.workSocket = sender;
byte[] byteData = Encoding.UTF8.GetBytes(data);
sender.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback((IAsyncResult e) =>
{
Socket socket = (Socket)e.AsyncState;
SocketBase.StateObject stateObject = new SocketBase.StateObject();
stateObject.workSocket = socket;
socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);
}), sender);
sender = RetrieveSocket(); //Socketreset
Thread.Sleep(100);
}
catch /*(Exception e)*/
{
//--
}
}
Server listener
public void StartListening()
{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(System.Int32.MaxValue);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
//--
}
}
public void AcceptCallback(...);
public void ReadCallback(...);
Socket send
private void Send(Socket handler, String data)
{
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.UTF8.GetBytes(data);
// Begin sending the data to the remote device.
t.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), t);
}
Socket send all data part (answer to getdata-request | socToHandle should be the socket of the previous connection of the getdata-request)
private void SendAllData(Socket socToHandle, string PakContent)
{
#region IsThereADatetime? //Resolve a given datetime
#region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)
Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket);
#region #SendResouces
#region #SendGroups
#region #SendTasks
}
Looking through my old code I have one idea =>
Could I send everything over the same connection by changing:
Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
(which creates a new connection) to something that uses the same connection?
If that would work, how can I do that?
And would the listener part of the client still receive single packets?
Servers and their environment are configured to handle incoming requests properly. Clients are usually behind a router, which by default make them unable to receive incoming connections from outside their network (a good thing).
To enable incoming connections, you could configure your router to forward all requests for a certain port number to your machine. No one else on your network would be able to run the client then, though.
This is why in a typical multiple clients-single server environment, the client makes all the connections, and only the server requires any changes to the network landscape.
I don't know why you chose to connect to the clients from the server side, but I would strongly advise against this - any cheap solution that uses this mechanism may turn out to be very expensive in the end.
I followed the example in MSDN about C# socket programming.
private static void StartClient() {
// Connect to a remote device.
try {
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect( remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client,"This is a test<EOF>");
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
I've created a simple test application that works.
The app sends and receives the response almost instantaneous.
So now the challenge is to implement the solution where the socket connects to an external device that will process the information from the socket and then send back a response.
At the line "Send test data to the remote device" --> the device receives this information at processes.
The debug keeps on going. The process is still going on in the remote device because I can see the data churning away.
But once it gets to receiveDone.WaitOne(); the debug is gone and the application hangs.
The problem here is the remote server is still processing. When it is done it is supposed to send back a response. Nothing happens.
Since I'm not that experienced with socket coding, I was wondering if anyone has run into this before. And if yes, how would I go about solving this issues so I can get a response back and the application doesn't hang?
Update:
I feel like smacking myself in the head.
The issue isn't with the WaitOne().
The debug is gone from WaitOne() because it's waiting for a response.
When the response comes, it goes to Receive() which then calls ReceiveCallback().
private void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
//THIS IS WHERE THE CODE DOESN'T CONTINUE.
}
catch (Exception e)
{
string error = e.InnerException.ToString();
}
}
When ReceiveCallback() is complete and it finishes getting all the data - it stops. It doesn't go back to my code where I initiate the sending and receiving of data.
It's supposed to go:
1. Get input request string
2. Pass it to the socket code
3. Socket code sends input request string
4. Socket code receives response string
5. Take the response string and do something with it
So it stops at #4 and ends without completing all the steps.
Am i missing code for it to continue the flow? Or have I set the process up incorrectly?
Thanks again for the help.
#John - thanks for updating my title. I'll try to keep the title in mind for the future.
========================================
UPDATE 2:
If I change the code and do not use the Receive() as it is in the MSDN sample, MSDN sample link and do something like:
var response = client.Receive(buffer);
var message = Encoding.ASCII.GetString(buffer);
This would work and everything continues. I need to make sure that the response isn't cut off though. But then that would defeat the purpose of it by async client correct?
Hmm....
thanks again for everyone's input.
OK. I got it after seeing how I went wrong.
I didn't check for the end response. I assumed that the end of the buffer transmission would set off the method that would return the response.
Thanks to everyone for your help. I couldn't have come to the solution without your help.
cheers!
I been reading a lot on how to implement UDP hole punching but fore some reason I cannot make it work.
For those that are not familiar of what udp hole punching is here is my own definition:
The goal is to be able to transfer data between two clients (Client A
and client B) with the help of a server. So client A connects to the server and sends its info. Client B does the same. The server has the nessesary info so that Client A is able to send data to Client B and vise versa . Therefore the server gives that info to both clients. Once both clients have that info about each other it is possible to start sending and receiving data between those clients without the help of the server.
My goal is to be able to do what I just described (udp hole punching). Before doing so I think it will be helpful to be able to connect from the server to the client. In order to do so I plan to send the server the info about the client. Once the server receives that info attempt to connect to the client from scratch. Once I am able to perform that I should have everything I need to start implementing the real udp hole punching.
Here is how I have things set up:
The top router has the server and bottom router connected to LAN ports. The bottom router (NAT) is connected to the top router via it's WAN port. And the client computer is connected to the bottom router to one of its LAN ports.
So in that connection the client is able to see the server but the server is not able to see the client.
So the algorithm I have done in pseudo code is:
Client connects to server.
Client send some UDP packages to the server in order to open some ports on the NAT
Send information to the server on what ports the client is listening to.
Once the server receives that info attempt to connect to the client from scratch.
Here is the implementation in code:
Server:
static void Main()
{
/* Part 1 receive data from client */
UdpClient listener = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
string received_data;
byte[] receive_byte_array = listener.Receive(ref groupEP);
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
// get info
var ip = groupEP.Address.ToString();
var port = groupEP.Port;
/* Part 2 atempt to connect to client from scratch */
// now atempt to send data to client from scratch once we have the info
Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint endPointClient = new IPEndPoint(IPAddress.Parse(ip), port);
sendSocket.SendTo(Encoding.ASCII.GetBytes("Hello"), endPointClient);
}
Client:
static void Main(string[] args)
{
/* Part 1 send info to server */
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse("192.168.0.132");
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, 11000);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
/* Part 2 receive data from server */
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer);
}
For some reason it worked a few times! It works when the client receives data successfully on the line: sending_socket.Receive(buffer);
Things to note:
If on the server on the second part I used the instance variable listner instead of creating the new variable sendSocket and send the bytes through that variable the client is able to receive the data being sent. Remember that the second part of the server is going to be implemented by a second client B that's why I am initializing variables again from scratch...
Edit:
Here is a different way of looking at the same problem. When I initialize a new object instead of using the same object the client does not receives the response.
I have a object of type UdpClient. I am able to send data with that object to the other peer. If I create another object of the same type with the same properties and attempt to send data it does not work! I might be missing to initialize some variables. I am able to set private variables with reflection so I should not have a problem. anyways here is the server code:
public static void Main()
{
// wait for client to send data
UdpClient listener = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
byte[] receive_byte_array = listener.Receive(ref groupEP);
// connect so that we are able to send data back
listener.Connect(groupEP);
byte[] dataToSend = new byte[] { 1, 2, 3, 4, 5 };
// now let's atempt to reply back
// this part does not work!
UdpClient newClient = CopyUdpClient(listener, groupEP);
newClient.Send(dataToSend, dataToSend.Length);
// this part works!
listener.Send(dataToSend, dataToSend.Length);
}
static UdpClient CopyUdpClient(UdpClient client, IPEndPoint groupEP)
{
var ip = groupEP.Address.ToString();
var port = groupEP.Port;
var newUdpClient = new UdpClient(ip, port);
return newUdpClient;
}
the client code basically sends data to the server and then waits for a response:
string ipOfServer = "192.168.0.132";
int portServerIsListeningOn = 11000;
// send data to server
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(ipOfServer);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
// now wait for server to send data back
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer); // <----- keeps waiting in here :(
note that the client is behind a router (NAT) otherwise I will not have this problem. The reason why I will like to copy udpClient is so that I can send that variable to another computer enabling the other computer to send data to the client.
So my question is why is the original object listener able to send data but newClient is not able to? The client keeps waiting at line sending_socket.Receive(buffer); even after the server executes the line: newClient.Send(dataToSend, dataToSend.Length);. the client successfully receives data when listener sends the data but not newClient. Why is this if both variables have the same destination IP and port? how do the variables differ?
Note:
If the server and client are on the same network then the copy works and variable newClient is able to send data to the client. To simulate this problem the client must be behind a NAT (router). An example of such network may consist of two routers. let's call them router X and router Y. You also need a Server call that S. and a client C. so S can be connected to one of the LAN ports of X. C can be connected to one of the LAN ports of Y. Finally connect the WAN port of Y to one of the LAN ports of X.
Hmm, I think you are confusing several things here. For one thing, it's really called UDP hole punching. Let me try to explain how this should work.
NAT routers usually do port mapping when forwarding packets from the inside private network to the outside internet.
Say you created a UDP socket on a machine behind NAT, and sent a datagram to some external IP/port. When the IP packet carrying that datagram leaves the sending machine, its IP header has the source address field set to local not-globally-routable private IP address (like 192.168.1.15), and UDP header has the source port field set to whatever port was assigned to the socket (either explicitly via binding, or implicitly picked by the OS from the ephemeral ports). I'll call this source port number P1.
Then when the NAT router sends that packet out on the outside network, it overwrites the source IP address to its own external IP address (otherwise there's no way to route packets back), and often overwrites the source UDP port to some other value (maybe because some other host on the private network uses the same source port, which creates ambiguity). The mapping between the original source port and that new port number (let's label it P2) is preserved in the router to match return packets. This mapping might also be specific to the target IP address and target UDP port.
So now you have "punched a hole" in the router - UDP packets sent back to the router to port P2 are forwarded to internal machine on UDP port P1. Again, depending on NAT implementation, this could be restricted to only packets from the original target IP address and target UDP port.
For client-to-client communication you'll have to tell external IP/port of one to the other through the server, hoping that the NAT router maps same internal source ports to same external source ports. Then the clients will send packets to each other using those.
Hope this helps.
Finally found the answer! Here is the implemenation with just a client and a server. My next attempt will be to use 3 computers. anyways hope this helps:
Server code:
class Program
{
static byte[] dataToSend = new byte[] { 1, 2, 3, 4, 5 };
// get the ip and port number where the client will be listening on
static IPEndPoint GetClientInfo()
{
// wait for client to send data
using (UdpClient listener = new UdpClient(11000))
{
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
byte[] receive_byte_array = listener.Receive(ref groupEP);
return groupEP;
}
}
static void Main(string[] args)
{
var info = GetClientInfo(); // get client info
/* NOW THAT WE HAVE THE INFO FROM THE CLIENT WE ARE GONG TO SEND
DATA TO IT FROM SCRATCH!. NOTE THE CLIENT IS BEHIND A NAT AND
WE WILL STILL BE ABLE TO SEND PACKAGES TO IT
*/
// create a new client. this client will be created on a
// different computer when I do readl udp punch holing
UdpClient newClient = ConstructUdpClient(info);
// send data
newClient.Send(dataToSend, dataToSend.Length);
}
// Construct a socket with the info received from the client
static UdpClient ConstructUdpClient(IPEndPoint clientInfo)
{
var ip = clientInfo.Address.ToString();
var port = clientInfo.Port;
// this is the part I was missing!!!!
// the local end point must match. this should be the ip this computer is listening on
// and also the port
UdpClient client = new UdpClient(new IPEndPoint( IPAddress.Any, 11000));
// lastly we are missing to set the end points. (ip and port client is listening on)
// the connect method sets the remote endpoints
client.Connect(ip, port);
return client;
}
}
client code:
string ipOfServer = "192.168.0.139";
int portServerIsListeningOn = 11000;
// send data to server
Socket sending_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress send_to_address = IPAddress.Parse(ipOfServer);
IPEndPoint sending_end_point = new IPEndPoint(send_to_address, portServerIsListeningOn);
sending_socket.SendTo(Encoding.ASCII.GetBytes("Test"), sending_end_point);
// get info
var port = sending_socket.LocalEndPoint.ToString().Split(':')[1];
// now wait for server to send data back
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, int.Parse(port));
byte[] buffer = new byte[1024];
sending_socket.Receive(buffer); // <----- we can receive data now!!!!!
Have you considered using UPnP on the client to configure NAT traversal to allow incoming packets on a particular port? The client would then only need to communicate the inbound IP and port to the server, and wait for the server to send packets.
http://en.wikipedia.org/wiki/Universal_Plug_and_Play
Seems you are able to connect with the server first time.After successful connection you need to close and disconnect the connection each time.Please check this sample code
http://codeidol.com/csharp/csharp-network/Connectionless-Sockets/A-Simple-UDP-Application/