I have been working with sockets to send data in C# and it's working, with this code:
string ipAddress = "x.y.z.a"; // replace with a real IP address
int port = 2809;
string data = "foo";
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (!clientSocket.Connected)
clientSocket.Connect(IPAddress.Parse(ipAddress), port);
clientSocket.Send(Encoding.UTF8.GetBytes(data));
clientSocket.Disconnect(true);
clientSocket.Close();
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Now I want it to receive data, but I can't get it to work because when I add socket.Receive()
the program crashes. Could anyone point me to the right direction?
As Jon is suggesting, it's not quite clear where you are trying to add the receive code. I mean, the last line(s) of your example is a bit confusing in that you first close the socket, then create a new one. Why? Similar with the "if (!clientSocket.Connected)" stuff first; if you create a fresh socket, there should be no need whatsoever to check if it is connected. Of course it's not, you just created it! :-)
Anyway, if I just add some code after yours like this:
byte[] receiveBuffer = new byte[1024];
clientSocket.Receive(receiveBuffer);
...and change the ipAddress
and port
accordingly, to a known good service on my network, I get a SocketException
with a message saying "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".
However, if I insert the receiving code so that the send/receive looks like this:
int bytesSent = clientSocket.Send(Encoding.UTF8.GetBytes(data));
var receiveBuffer = new byte[1024];
var sb = new StringBuilder();
int receivedBytes;
while ((receivedBytes = clientSocket.Receive(receiveBuffer)) != 0)
{
// NOTE: this presumes that the data coming from the remote end is ASCII-
// encoded, which might not be the case at all. Don't copy this approach
// blindly without thinking
string s = Encoding.ASCII.GetString(receiveBuffer, 0, receivedBytes);
sb.Append(s);
}
var response = sb.ToString(); // at this point you should have all the data that
// has been received from the remote, so far.
clientSocket.Disconnect(true);
clientSocket.Close();
This code works for me; it gives me the response to my request (around 3 KiB in my case).
On a more philosophical/architectural level, I definitely suggest though, that if you don't really need to go down to the socket level (for whatever reason) to prefer using one of the more high-level classes of the framework. WebClient is one alternative (works with all >1.1 versions of the framework, e.g. virtually all versions in active use today). HttpClient is another one, if you are on .NET 4.5 (there is a back-port available also from NuGet.
Of course, this blindly presumes that what you want to do is to perform HTTP requests (which, it turns out, is quite common these days). There are also other alternatives like FtpWebRequest for FTP, etc etc.
In my experience (working as a programmer for a bit more than 10 years), it's actually very uncommon to have to go down as deep as to the socket level, especially recently given how much of the common scenarios are supported in the BCL (base class library, e.g. the .NET standard assemblies provided by Microsoft) or NuGet. Such existing clients have the huge, huge advantage of other people having spent a considerable amount of time on it, nailing out the bugs, quirks and so forth, so you can start focusing on the problem you really want to solve, rather than fixing bugs which have actually been fixed many, many times before...
(Of course, there are exceptions, but I feel this is definitely the general rule of thumb.)