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.
Related
I'm working on a piece of code, where a connection is made to a TCP socket.
The code contains the following excerpt:
// Close the socket if it is still open
if (_socket != null)
{
Disconnect();
}
// Create the socket object
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
The DisConnect() method does (amongst other things):
var socket = _socket;
_socket = null;
socket.Close();
I don't understand the beginning: why disconnect in order to connect?
I have tried removing that part of the code, but then the whole thing became very unstable.
Does anybody have an idea?
Thanks
Once a TCP socket has been closed, it can't be reused, so a new socket is needed for a new TCP connection.
If you want to reuse the same socket for a new TCP connection after a disconnect, you need to use the Socket.Disconnect() method with the reuseSocket parameter set to true.
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'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.
Well, I wonder if some one can help with a problem that I encounter....
I want to close a socket and then rerun from the same port. This is what i am doing...
opening:
UdpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
UdpServerIpEndPoint = new IPEndPoint(IPAddress.Any, 9050);
UdpEndPoint = (EndPoint)UdpServerIpEndPoint;
UdpServer.Bind(UdpServerIpEndPoint);
closeing:
UdpServer.Shutdown(SocketShutdown.Both);
UdpServer.Disconnect(true);
UdpServer.Close();
After I close it. and the I try to reconnect it with the same code as above, I get error:
Additional information: Only one usage of each socket address
(protocol/network address/port) is normally permitted
I checked for exception during closing, but I didnt get any, i guessed they were closed properly, so actually, what is causing this problem? Please help!
I got answer....
I need to use this after decleration of socket...
socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress, true);
You could look at this 2 ways.
Don't actually Receive whilst your are in your stopped state, just in your BeginReceive, just drop/ignore the data
If you really need to recreate the socket, then don't perform the disconnect on your Server because you haven't actually got a connection. Your disconnect is throwing
System.Net.Sockets.SocketException (0x80004005): A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
For reference, in case anyone else stumbles onto this question but looking for the UdpClient implementation.
int port = 1234;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var endPoint = new IPEndPoint(IPAddress.Any, port);
socket.Bind(endPoint);
var updClient = new UdpClient();
updClient.Client = socket;
updClient.Connect(_ipAddress, port);
In .NET CF on a Windows CE 5.0 based POS device, if no connection (GPRS/WiFi) is available, when i try to connect my socket object i don't get any exceptions, even after it, when i try to send bytes to somewhere by Socket.SentTo() method i don't get any exceptions too! And even the returned value indicating the size of totally sent bytes is correct! what's the matter? how can i ensure of the health of the operations?
pieces of my code:
Socket m_socClient = new Socket(
AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAdd = IPAddress.Parse("192.168.7.80");
IPEndPoint remoteEP = new IPEndPoint(ipAdd, 2415);
m_socClient.Connect(remoteEP); // No exception!
// why works?
int iSent = m_socClient.SendTo(byData, byData.Length,
SocketFlags.None, remoteEP);
Few suggestions:
Check the Connected property of the connection
I understand SendTo is more suited for connectionless protocols, and Send() is better suited for Connection-oriented protocols like TCP.
Send() (and I expect SendTo()) may have no effect if there is no data to send. Have you checked there is data?