I am trying to learn socket programming in C#
By using google I found a lot of good tutorials and examples.
But here is my own code :
Sender application :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net; // socket library
using System.Net.Sockets; // socket library
namespace Sender
{
class Program
{
static void Main(string[] args)
{
Console.Write("Enter remote IP : ");
IPAddress ipAddress = IPAddress.Parse(Console.ReadLine());
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sender.Connect(ipAddress, 4444);
Console.Write("Enter text to send : ");
byte[] message = Encoding.ASCII.GetBytes(Console.ReadLine().ToString());
sender.Send(message);
sender.Shutdown(SocketShutdown.Both);
sender.Close();
Console.ReadKey();
} // main
} // main
} // main
Receiver application :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net; // socket library
using System.Net.Sockets; // socket library
namespace Listener
{
class Program
{
static void Main(string[] args)
{
IPAddress ipAddress = Dns.GetHostAddresses(Dns.GetHostName()).Where(address => address.AddressFamily == AddressFamily.InterNetwork).First();
Console.WriteLine("Listening on " + ipAddress.ToString() + " : 4444");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 4444);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(10);
Socket handler = listener.Accept();
byte[] bytes = new Byte[1024];
int bytesRec = handler.Receive(bytes);
Console.WriteLine(Encoding.ASCII.GetString(bytes, 0, bytesRec));
handler.Shutdown(SocketShutdown.Both);
handler.Close();
listener.Close();
Console.ReadKey();
} // main
} // main
} // main
The code works fine, but I want to know why do I need two sockets in server side? The first one is listener and the second one is handler. Is it possible to omit one of them so that the code become more simple?
By the way my code is based on these codes :
Synchronous Client Socket Example : https://learn.microsoft.com/en-us/dotnet/framework/network-programming/synchronous-client-socket-example
Synchronous Server Socket Example : https://learn.microsoft.com/en-us/dotnet/framework/network-programming/synchronous-server-socket-example
Also I am using Microsoft Visual C# 2008 Express Edition
The listener socket is listening for the incoming connections. If there were no handler socket, then there were no one to listen for parallel incoming connections until the communication with the client is over.
That's why Accept returns another socket, which is used for communication, and the listening socket continues waiting for incoming connections.
You can see it as a kind of weakly-typed objects: the Socket is responsible for both listening and communication roles, although it might be better to have different types for these two different tasks. But this behaviour reflects the traditional socket behaviour, so it remains as it is in order to be familiar to the people having background in network programming.
The more high-level API (TcpListener and TcpClient) makes a clear distinction between listening and communication roles.
Related
I have created a hub in SignalR in my web project. In my hub class I want to receive udp data sent on port no 4001. Please suggest the code to receive data through udp socket. I tried to receive using the code as shown below but it gives error "System.Net.Sockets.SocketException: 'Only one usage of each socket address (protocol/network address/port) is normally permitted"
ClockHub.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace RealTimeClock.App_Code
{
public class ClockHub : Hub
{
public void getSocketData()
{
// Here I want to receive udp socket data on port 4001
// my code commented here did not work
//UdpClient receivingUdpClient = new UdpClient(11000);
//IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
//Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
//string UDP_Rx_Data= Encoding.ASCII.GetString rceiveBytes);
Clients.Caller.setTime(UDP_Rx_Data);
}
}
}
I can send UDP messages from one computer to itself on a certain port but I can't send this messages from one computer to another in the same lan. I am pretty new to C# and I am also new to network programming so the solution is probably easy...
I have tried an example from Microsoft Docs and did only small changes. (names, etc.)
Both codes run as seperate programs.
//RECEIVE
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class UDPListener
{
private const int listenPort = 11000;
private static void Listen()
{
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
try
{
while (true)
{
Console.WriteLine("Waiting for broadcast");
byte[] receivebytes = listener.Receive(ref groupEP);
Console.WriteLine(Encoding.ASCII.GetString(receivebytes, 0, receivebytes.Length));
}
}
catch (SocketException e)
{
Console.WriteLine(e);
}
finally
{
listener.Close();
}
}
public static void Main()
{
Listen();
}
}
//SEND
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class Program
{
static void Main(string[] args)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//192.168.2.5 is the IP Address of the receiving computer
IPAddress broadcast = IPAddress.Parse("192.168.2.5");
byte[] bytestosend = Encoding.ASCII.GetBytes("Hi");
IPEndPoint ep = new IPEndPoint(broadcast, 11000);
socket.SendTo(bytestosend, ep);
Console.WriteLine("bytestosend were send");
}
}
The sending program tells me that the message was sent but the receiving program gives no output.
EDIT 1: The Ressource Manager said that on the receiving computer was no network activity while on the sending computer is actually sending something.
EDIT 2: I tried my applications in an other network and it worked fine. I did some research and I found that sometimes routers don't allow udp broadcasts through a subnet (or anything similar...). So I assume it might be my router. (unfortunately I can not access it's settings.) So I think the problem has resolved itself!
I want to write a part of code in which I start sending packages using tcp stream, but without any part that receives it over the internet.
In the meantime I would also like to have another method that can connect to that particular stream at any time and starts receiving bytes from the moment it connects.
I wanted to use multicasting, but I see it's impossible to do it over the Internet
Is there a way to do it? I only found some info so far, that the tcp connection in C# uses point to point way, so my case sounds impossible to implement, because the listener has to be always active to even initialize the streamer, how can I bypass that?
Edit Added an example of a simply "broker" who republishes all messages it receives.
Either use UDP and broadcast your packets to an endpoint that may or maynot be listening at any point in time.
Or use a message queue such as MSMQ, RabbitMQ or 0MQ.
MSMQ may become a problem if the listening service is offline for to long as the messages queue on your dispatch system resulting in a backlog that may fill.
If you would like to create something using UDP here is some code.
Listener (server):
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPLISTENER
{
class Program
{
static void Main(string[] args)
{
var port = 8750;
var listener = new UdpClient(port);
var group = new IPEndPoint(IPAddress.Any, port);
Console.WriteLine("Listening for datagrams on port {0}", port);
while(true)
{
var data = listener.Receive(ref group);
Console.WriteLine("{0}: {1}", group.ToString(), Encoding.Default.GetString(data, 0, data.Length));
}
}
}
}
Broker (Server&Client):
sing System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPCLIENT
{
class Program
{
static void Main(string[] args)
{
int listeningPort = 8749, dispatchPort = 8750;
var listener = new UdpClient(listeningPort);
var group = new IPEndPoint(IPAddress.Any, listeningPort);
// Republish client
var sender = new UdpClient("127.0.0.1", dispatchPort);
Console.WriteLine("Listening for datagrams on port {0}", listeningPort);
while (true)
{
var data = listener.Receive(ref group);
Console.WriteLine("{0}: {1}", group.ToString(), Encoding.Default.GetString(data, 0, data.Length));
sender.Send(data, data.Length);
}
}
}
}
Sender (Client):
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace UDPSENDER
{
class Program
{
static void Main(string[] args)
{
var sender = new UdpClient("127.0.0.1", 8749);
while (true)
{
Console.WriteLine("Message: ");
var data = Encoding.Default.GetBytes(Console.ReadLine());
sender.Send(data, data.Length);
}
}
}
}
Depending what you wish to archive I recommend message queues they give to the most flexibility.
But as you can see UDP works a bit differently to TCP. You don't need a handshake like TCP does, this means if no one is listening to your messages they vanish with no cost to the sender (there is still cost to the network). But if a listener pops up then they start consuming the messages right away. Remember no UDP packet is guaranteed delivery, this is both a blessing and a curse.
If you want messages to be guaranteed you need to implement your own solution, one method is a counter on the datagrams that the listener watches if there is a message missing then it request that message be resent.
You can create a new class derived from Stream, override the Write method, and manage the writing to the tcp clients here. You will be able to write to this stream from your code whether a client is connected or not. When no client is connected, the data will simply be ignored.
I have a client-server application that uses a UDP socket to send the data , the data only have to travel from client to server , and the server will always have the same IP. The only requirement is that I have to send messages about 10 messages per second
Currently I am doing it the following way :
public void SendData(byte[] packet)
{
IPEndPoint end_point = new IPEndPoint(serverIP, serverPort);
UdpClient udpChannel = new UdpClient(sourcePort);
udpChannel.Connect(end_point);
udpChannel.Send(packet, packet.Length);
udpChannel.Close();
}
The problem I have is that when I use the command "udpChannel.Close()" it takes 2-3 seconds to be performed when the server is not listening. (I've seen the same problem in: What is the drawback if I do not invoke the UdpClient.Close() method?)
My question would be, if I always send packets to the same IP address and port, is it necessary to connect the socket and close it after each send request?
The code I intend to use would be as follows:
UdpClient udpChannel;
public void SendData(byte[] packet)
{
udpChannel.Send(packet, packet.Length);
}
public void Initialize(IPAddress IP, int port)
{
IPEndPoint end_point = new IPEndPoint(serverIP, serverPort);
UdpClient udpChannel = new UdpClient(sourcePort);
udpChannel.Connect(end_point);
}
public void Exit()
{
udpChannel.Close();
}
Doing it this way, would it be necessary to do some checking in the "SendData" method before sending the data?
Is there any problem in the above code?
Thank you!
UDP is connectionless, calling udpChannel.Connect merely specifies a default host endpoint for use with the Send method. You do not need to close the client between sends, leaving it open will not leave any connections or listeners running between sends.
You shouldn't connect/close after each send request. When you start working - you connect to socket. And you can send data. You should close UdpClient when you do not want to send/recieve data, for example when you closing Form.
In your case you can check that udpClient != null when close/send client and you can use try/catch, for example:
try
{
udpClient.Send(sendBytes, sendBytes.Length);
}
catch (Exception exc)
{
// handle the error
}
Use try/catch when you connecting, because port may be busy or other problem with connection.
And look at UdpClient.SendAsync :)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System.Text;
using System.Net.Sockets;
using System;
using System.Net;
public class Server : MonoBehaviour
{
//int[] ports;
UdpClient udp; // Udp client
private void Start()
{
udp = new UdpClient(1234);
udp.BeginReceive(Receive, null);
}
void Send(string msg, IPEndPoint ipe)
{
UdpClient sC = new UdpClient(0);
byte[] m = Encoding.Unicode.GetBytes(msg);
sC.Send(m, msg.Length * sizeof(char), ipe);
Debug.Log("Sending: " + msg);
sC.Close();
}
void Receive(IAsyncResult ar)
{
IPEndPoint ipe = new IPEndPoint(IPAddress.Any, 0);
byte[] data = udp.EndReceive(ar, ref ipe);
string msg = Encoding.Unicode.GetString(data);
Debug.Log("Receiving: " + msg);
udp.BeginReceive(Receive, null);
}
}
At the Send() I use new UDP CLient and close it after every time. Its better, u can send and receive at the same time.
I am trying to forward multiple sockets communication to a target socket. So I need to make multiple connection to that target socket, but when I try to connect to it for the second time, I get this:
SocketException: No connection could be made because the target machine actively refused it
I think the problem is with the other end of the socket, i.e port and host and because there is already a connection between port related to my program and target port, to have a second connection I need a second port for my program.
I hope my problem be clear for you guys.
Any Idea how to do it?
This is a test program just to show the problem.
using System;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Text;
class Sample
{
private static ManualResetEvent connectDone = new ManualResetEvent(false);
public static void Main()
{
Socket[] s = new Socket[10];
for (int i = 0; i < s.Length; i++)
{
IPAddress ipAddress;
ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndp = new IPEndPoint(ipAddress, 1100);
// Create a TCP/IP socket.
s[i] = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
connectDone.Reset();
s[i].BeginConnect(localEndp,
new AsyncCallback(ConnectCallback), s[i]);
connectDone.WaitOne();
s[i].Send(Encoding.ASCII.GetBytes(i.ToString() + ": hi.\r\n"));
}
}
private static void ConnectCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
// Signal that the connection has been made.
connectDone.Set();
}
}
I even tried to bind my sockets to different ports, but still second socket gets that exception.
This error message means that there is no open port on that IP. The IP is valid but the remote host replied that it will not accept a connection on this port.
You should be getting this error even for the very first connection.
Find out why the port is not open.
Btw, you use of async connect is counter-productive. You have non of the async benefits and all of the disadvantages. But this is not the point of this question.