I've tried multiple methods of doing this, and non seem to work out. But there must be a way.
What I'm trying to do (in C#) is create a server. I want the server to listen on a IP and port, and when it connects to a client, I want it to read what the client says, and send a reply. For the client, I want to connect to a server and send data, and receive the reply from the server.
How can I go about doing this?
I've used Microsoft examples and examples found on MSDN. They have Client > data > Server but it doesn't ever seem to include the server reply.
I know this can be done, obviously, because we have multiplayer games.
Thanks for the help.
EDIT - Code snippets
SERVER
static void Main(string[] args)
{
int recv;
byte[] data = new byte[1024];
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 904);
Socket newSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
newSocket.Bind(endPoint);
Console.WriteLine("Listening for connections...");
//LISTEN FOR CLIENT
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 904);
EndPoint tmpRemote = (EndPoint)sender;
//READ MESSAGE FROM CLIENT
recv = newSocket.ReceiveFrom(data, ref tmpRemote);
Console.WriteLine("Messaged received from: " + tmpRemote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
string welcome = "Welcome to server!";
data = Encoding.ASCII.GetBytes(welcome);
//SEND WELCOME REPLY TO CLIENT
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.Bind(tmpRemote);
sock.SendTo(data, tmpRemote);
Console.WriteLine("Reply sent to client");
while (true)
{
if(!newSocket.Connected)
{
Console.WriteLine("Client disconnected.");
break;
}
data = new byte[1024];
recv = newSocket.ReceiveFrom(data, ref tmpRemote);
if (recv == 0)
break;
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
}
newSocket.Close();
Console.WriteLine("Server disconnected.");
Console.ReadLine();
}
}
CLIENT
static void Main(string[] args)
{
Console.WriteLine("Message [127.0.0.1:904]: ");
string msg = Console.ReadLine();
byte[] packetData = ASCIIEncoding.ASCII.GetBytes(msg);
string IP = "127.0.0.1";
int port = 904;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(IP), port);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.SendTo(packetData, ep);
Console.WriteLine("Data sent!");
int recv;
byte[] data = new byte[1024];
EndPoint tmpRemote = (EndPoint)ep;
while(true)
{
//READ MESSAGE FROM SERVER
recv = client.ReceiveFrom(data, ref tmpRemote);
Console.WriteLine("Messaged received from: " + tmpRemote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
}
client.Close();
Console.WriteLine("Client disconnected.");
Console.ReadLine();
}
I can't get the server to talk back to the client and have the client read/display the server's reply.
change this sentence
sock.SendTo(data, tmpRemote);
to
newSocket.SendTo(data, tmpRemote);
and remove these sentences, you have bind local EndPoint twice.
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.Bind(tmpRemote);
In Net, you can use UdpClient instead of Socket.
If you want a demo, look at this demo.
Related
I have an udp client server source on C# and now I have a problem: I test my source on localhost but it doesn't receive on long way connections for example a VPS to a client.
Client:
private static void StartListener()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
try
{
while (!done)
{
byte[] bytes = listener.Receive(ref groupEP);
Thread.Sleep(100);
byte[] dcbufresponse = new byte[512];
dcbufresponse = Encoding.ASCII.GetBytes("0xc00901");
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ipaddresssv), 9052);
s.SendTo(dcbufresponse, dcbufresponse.Length, SocketFlags.None, ipep);
done = true;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
listener.Close();
}
}
Server :
private static Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
private static IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ipnow), 9052);
s.SendTo(dcbuf, dcbuf.Length, SocketFlags.None, ipep);
Console.WriteLine("sended");
sended.Add(ipnow);
try
{
listener.Client.ReceiveTimeout = 5000;
byte[] bytes = listener.Receive(ref groupEP);
string dcresponse = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
Console.WriteLine(dcresponse);
}
Problem is this : client doesn't receive anything and client can not send to server after receiving ...
Edit :
My Serve Have Two Ip Address !
and i thinking that i must bind once of my two ip address to my udp client :-?
do you think that its work ?
I try to send message to all members of the group. Sender:
// Create socket
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Multicast IP-address
IPAddress ip = IPAddress.Parse("224.168.55.25");
// Join multicast group
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip));
// TTL
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
// Create an endpoint
IPEndPoint ipep = new IPEndPoint(ip, 4567);
// Connect to the endpoint
s.Connect(ipep);
// Scan message
while (true)
{
byte[] buffer = new byte[1024];
string msg = Console.ReadLine();
buffer = Encoding.ASCII.GetBytes(msg);
s.Send(buffer, buffer.Length, SocketFlags.None);
if (msg.Equals("Bye!", StringComparison.Ordinal))
break;
}
// Close socket
s.Close();
Receiver:
// Create new socket
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Create IP endpoint
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 4567);
// Bind endpoint to the socket
s.Bind(ipep);
// Multicast IP-address
IPAddress ip = IPAddress.Parse("224.168.55.25");
// Add socket to the multicast group
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));
// Receive messages
while (true)
{
byte[] data = new byte[1024];
s.Receive(data);
string str = System.Text.Encoding.ASCII.GetString(data, 0, data.Length);
Console.WriteLine(str.Trim());
if (str.Equals("Bye!", StringComparison.Ordinal))
{
break;
}
}
I don't uderstand why there is a lot of free space between messages when I print them to screen on the client side? Why loop in the Receiver program doesn't stop after receiveing message Bye!? How can I fix this problems?
Thank you very much!
You are creating a udp socket. Udp sockets are not connection oriented. So it just receives messages and has no idea about the state of the sender. Even if the sender socket closes, the receiver would keep on listening.
I hope I have understood your question correctly.
if (strData.Trim().Equals("Bye!", StringComparison.Ordinal))
{
Console.WriteLine("that's right");
break;
}
Socket.Receive() return the bytes received you should use the return value to generate the string, or you will get a string with the length of 1024 and Trim cannot handle it.
int len = s.Receive(data);
string str = System.Text.Encoding.ASCII.GetString(data, 0, len);
I have a program that multiple clients would be able to connect to a server using a socket:
private void performConnect()
{
while (true)
{
if (myList.Pending())
{
thrd = thrd + 1;
tcpClient = myList.AcceptTcpClient();
IPEndPoint ipEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint;
string clientIP = ipEndPoint.Address.ToString();
nStream[thrd] = tcpClient.GetStream();
currentMsg = "\n New IP client found :" + clientIP;
recieve[thrd].Start();
this.Invoke(new rcvData(addNotification));
try
{
addToIPList(clientIP);
}
catch (InvalidOperationException exp)
{
Console.Error.WriteLine(exp.Message);
}
Thread.Sleep(1000);
}
}
}
then the server could send data (chat messages) to a chosen client, using this code.
private void sendData(String data)
{
IPAddress ipep =IPAddress.Parse(comboBox1.SelectedItem.ToString());
Socket server = new Socket(AddressFamily.InterNetwork , SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipept = new IPEndPoint( ipep, hostPort);
NetworkStream nStream = tcpClient.GetStream();
ASCIIEncoding asciidata = new ASCIIEncoding();
byte[] buffer = asciidata.GetBytes(data);
if (nStream.CanWrite)
{
nStream.Write(buffer, 0, buffer.Length);
nStream.Flush();
}
}
the problem is that whatever IP i choose from the combo box, the message i send would always be directed/sent to the last IP that connected to the server.. Please somebody pinpoint my error! all help would be appreciated.
Look at those lines:
IPAddress ipep =IPAddress.Parse(comboBox1.SelectedItem.ToString());
Socket server = new Socket(AddressFamily.InterNetwork , SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipept = new IPEndPoint( ipep, hostPort);
NetworkStream nStream = tcpClient.GetStream();
You are creating a new socket but you are sending the data to the socket stored in the variable tcpClient that is global (since it was not defined in the method), thus totally ignoring the IPEndPoint parsed from the combobox.
You should not create a new socket in order to send data to the clients. Instead, store all clients in a collection and retrieve the appropriate one based on the input of the combobox.
I'm working with sockets in C# and I'm getting the following error:
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
Here is the code that I'm executing:
private void HostSubscriberService()
{
IPAddress ipV4 = PublisherService.ReturnMachineIP();
var localEP = new IPEndPoint(ipV4, _port);
var server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(localEP);
StartListening(server);
}
private void StartListening(Socket server)
{
EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
var data = new byte[1024];
int recv = server.ReceiveFrom(data, ref remoteEP);
string messageSendFromClient = Encoding.ASCII.GetString(data, 0, recv);
MessageBox.Show(messageSendFromClient);
}
}
The error happens # int recv = server.ReceiveFrom(data, ref remoteEP);
I just need to listen for new incoming connections and then print the message that was sent from the new client.
I need it to work on the TCP protocol, because some of the messages will be > 1500 bytes
Thanks!
You need to .BeginAccept() before you can receive.
Here's a link with a sinple Asynchronous Socket Server example
ReceiveFrom() is for UDP, use Accept() and Receive() for TCP
As kind of a followup to this question I've gotten a solution working on my local machine, but not on a machine on the network.
I don't know too much about sockets other than that basics, so bear with me. The goal is for a client to look for a server on a local network, and this is the result of some cut/paste/edit code.
This is the client code:
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10294);
byte[] data = new byte[1024];
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 10);
string welcome = "What's your IP?";
data = Encoding.ASCII.GetBytes(welcome);
client.SendTo(data, data.Length, SocketFlags.None, ipep);
IPEndPoint server = new IPEndPoint(IPAddress.Any, 0);
EndPoint tmpRemote = (EndPoint)server;
data = new byte[1024];
int recv = client.ReceiveFrom(data, ref tmpRemote);
this.IP.Text = ((IPEndPoint)tmpRemote).Address.ToString(); //set textbox
this.Port.Text = Encoding.ASCII.GetString(data, 0, recv); //set textbox
client.Close();
}
This is the server code:
int recv;
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 10294);
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
newsock.Bind(ipep);
newsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Any,IPAddress.Parse("127.0.0.1")));
while (true)
{
Console.WriteLine("Waiting for a client...");
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tmpRemote = (EndPoint)(sender);
data = new byte[1024];
recv = newsock.ReceiveFrom(data, ref tmpRemote);
Console.WriteLine("Message received from {0}:", tmpRemote.ToString());
Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));
string welcome = "7010";
data = Encoding.ASCII.GetBytes(welcome);
newsock.SendTo(data, data.Length, SocketFlags.None, tmpRemote);
}
It works find on my local machine (both server and client) but when I try another machine on the same network I get "An existing connection was forcibly closed by the remote host"
I realize I need to add a lot of try/catch but I'm just trying to get a handle on how this works first.
I have to start by saying that I know nothing about C#, but...
Looking at the definition of the ipep in the client code, it looks like you're trying to send your data to yourself, rather than broadcast it (as has been suggested in your other question). The thing that caught my attention was that "127.0.0.1" is the address of "localhost".
That would explain why it works nicely when you're running both the client and server on the one machine, as it will be sending to itself.
I would expect that correct endpoint would be for a broadcast address (eg. "255.255.255.255") - although you could also choose the broadcast address of the local network that you're on, depending on how widely you wish to broadcast.
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10294);
Should become:
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 10294);
And
newsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Any, IPAddress.Parse("127.0.0.1")));
Should Become
newsock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Any, IPAddress.Parse("255.255.255.255")));
I think.
OK, this doesn't work, so something's still wrong.