I am trying to get to grips with sockets and it is proving a bit harder than I thought. I have googled this error and have tried to fix it myself by toying with my code but I do not understand what is not right here. The following code is giving me a socket exception with the 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." As you can see I am trying this on my local machine, the client simply connects and sends a string. Any tips or pointers would be nice!
NOTE I have read other similar questions here on Stack Overflow but have not managed to fix my program with the solutions!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Server
{
class Program
{
private static Socket socket = null;
private static Socket client = null;
private static IPAddress ipAddress = null;
private static int port = 1090;
private static IPEndPoint endPoint = null;
private static byte[] buffer;
private static int socketRecv = 0;
static void Main(string[] args)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ipAddress = IPAddress.Parse(GetLocalIPv4(NetworkInterfaceType.Ethernet));
endPoint = new IPEndPoint(ipAddress, port);
buffer = new byte[1024];
Console.WriteLine("\nVariables initialized...");
socket.Bind(endPoint);
socket.Listen(5);
Console.WriteLine("\nSocket bound and listening...");
client = socket.Accept();
Console.WriteLine("\nSocket accepted connection...");
//the program gets to here, then the exception is thrown
while (true)
{
if (socketRecv == 0)
{
socketRecv = socket.Receive(buffer);
continue;
}
Console.WriteLine("\nData wrote...\n");
break;
}
Console.WriteLine(System.Text.Encoding.Default.GetString(buffer));
Console.Read();
}
public static string GetLocalIPv4(NetworkInterfaceType _type)
{
string output = "";
foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces())
{
if (item.NetworkInterfaceType == _type && item.OperationalStatus == OperationalStatus.Up)
{
foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
output = ip.Address.ToString();
}
}
}
}
return output;
}
}
}
Related
me and my friends are currently trying to build a chat application with c sharp in visual studio .
while doing that we bumped into the words "client network" and "server network" .
I ve been told that those are two dll files that provides a connection between my client , server and database . Can anyone explain to me what should these dll files contain and how to they contribute to our chat application ( I am still a beginner )
Thank you so much !
According to your description, you want to solve the communication between the client and the server.
I recommend that you use socket to realize the connection between server and client, and
create two DLL files to facilitate program reference.
It will be explained in detail below.
(1) ClientCommunication.dll
1: Establish a Socket object;
2: Use the Connect() method of the socket object to send the connection request to the server with the EndPoint object created above as a parameter;
3: If the connection is successful, use the Send() method of the socket object to send information to the server;
4: Use the Receive() method of the socket object to receive the information sent by the server;
5: Be sure to close the socket after the communication is over
(2) ServerCommunication.dll
1: Establish a Socket object;
2: Bind EndPoint with the Bind() method of the socket object;
3: Use the Listen() method of the socket object to start listening;
4: Accept the connection to the client, use the socket object's Accept() method to create a new socket object for communicating with the requesting client;
5: Use the new socket object to receive and send messages.
ServerCommunication.dll contains ServerSocket.cs
ServerSocket.cs code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ServerCommunication
{
public class ServerSocket
{
static Socket serverSocket;
public static void StartListening(IPAddress ip, int port)
{
serverSocket = new Socket(SocketType.Stream, ProtocolType.Tcp);
IPEndPoint point = new IPEndPoint(ip, port);
serverSocket.Bind(point);
Console.WriteLine("{0}Listen Success", serverSocket.LocalEndPoint.ToString());
serverSocket.Listen(10);
Thread myThread = new Thread(ListenClientConnect);
myThread.Start();
Console.ReadLine();
}
static void ListenClientConnect()
{
while (true)
{
Socket clientSocket = serverSocket.Accept();
clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));
Thread receiveThread = new Thread(ReceiveMessage);
receiveThread.Start(clientSocket);
}
}
static void ReceiveMessage(object clientSocket)
{
Socket myClientSocket = (Socket)clientSocket;
while (true)
{
try
{
//clientSocket accept
byte[] result = new byte[1024];
int receiveNumber = myClientSocket.Receive(result);
Console.WriteLine("Receive client{0}news{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result, 0, receiveNumber));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
myClientSocket.Shutdown(SocketShutdown.Both);
myClientSocket.Close();
break;
}
}
}
}
}
ClientCommunication.dll contains ClientSocket.cs
ClientSocket.cs code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ClientCommunication
{
public class ClientSocket
{
static byte[] result = new byte[1024];
public static void StartClient(IPAddress ip, int port)
{
Socket socketClient = new Socket(SocketType.Stream, ProtocolType.Tcp);
IPEndPoint point = new IPEndPoint(ip, port);
try
{
socketClient.Connect(point);
Console.WriteLine("Successfully connected to server!");
}
catch
{
Console.WriteLine("Failed to connect to the server, please press enter to exit!");
return;
}
//clientSocket accept
int receiveLength = socketClient.Receive(result);
Console.WriteLine("Receive server message:{0}", Encoding.ASCII.GetString(result, 0, receiveLength));
// clientSocket send
try
{
Thread.Sleep(1000);
string sendMessage = "client send Message Hellp" + DateTime.Now;
socketClient.Send(Encoding.ASCII.GetBytes(sendMessage));
Console.WriteLine("Send message to server:{0}" + sendMessage);
}
catch
{
socketClient.Shutdown(SocketShutdown.Both);
socketClient.Close();
}
Console.WriteLine("After sending, press enter to exit");
Console.ReadLine();
}
}
}
The specific use is as follows:
Server,cs code:
using ServerCommunication;
using System.Net;
namespace Server
{
class Server
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 8885;
ServerSocket.StartListening(ip,port);
}
}
}
Client.cs code:
using ClientCommunication;
using System.Net;
namespace Client
{
class Client
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 8885;
ClientSocket.StartClient(ip,port);
}
}
}
Operation results:
Server:
Client:
I am UsingClient.Send(Encoding.ASCII.GetBytes(Message)); to send a message to the client, when i tried sending a second message it doesn't give any error so i think it send with no problem but it never reaches the client (127.0.0.1)
Code That Send
public void SendMessage(Socket _Client, string Message)
{
foreach (Socket Client in Clients)
{
IPEndPoint TargetEndPoint = _Client.LocalEndPoint as IPEndPoint;
IPAddress TargetIp = TargetEndPoint.Address;
int TargetPort = TargetEndPoint.Port;
IPEndPoint ClientEndPoint = Client.LocalEndPoint as IPEndPoint;
IPAddress ClientIp = ClientEndPoint.Address;
int ClientPort = ClientEndPoint.Port;
if (TargetIp.ToString() == ClientIp.ToString() && TargetPort == ClientPort)
{
Client.Send(Encoding.ASCII.GetBytes(Message));
//Client.EndSend();
}
}
}
Code That Receive
private void RecivedCallBack(IAsyncResult Result)
{
//Create a int with the Buffer Size
int BufferSize = _Socket.EndReceive(Result);
//Create a new byte array with the Buffer Size
byte[] Packet = new byte[BufferSize];
//Copy Buffer to Packet
Array.Copy(_Buffer, Packet, Packet.Length);
//Handle Packet
PacketHandler.Packet(Encoding.UTF8.GetString(Packet));
//Makes _Buffer a new byte
_Buffer = new byte[1024];
//Get Ready to recive data
_Socket.BeginReceive(_Buffer, 0, _Buffer.Length, SocketFlags.None, RecivedCallBack, null);
}
Code that Handle
public static void Packet(string Message)
{
Console.WriteLine(Message);
switch (Message)
{
case "StartChat":
_ChatForm Start = new _ChatForm();
Start.ShowDialog();
break;
case "StopChat":
_ChatForm._Chat.EndChat();
break;
}
}
TCP is stream based, so your client has no way to know when the message has ended. Either use UDP, implement a way to detect the end of messages (eg send a 4 byte message with the length of the real message, before sending the real message... and read on the client until the whole message has been received), or use a library. I like Hazel: https://github.com/DarkRiftNetworking/Hazel-Networking.
The great thing about Hazel is that it implements reliable UDP. So, if you need to have your "messages" arrive in the order in which they were sent, or if you need guaranteed delivery and receipt of such messages (such as what TCP provides), then you can do so with their reliable UDP implementation.
They will also implement Web Sockets at some point :) Good luck!
A client/server example from the documentation:
Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using Hazel;
using Hazel.Tcp;
namespace HazelExample
{
class ServerExample
{
static ConnectionListener listener;
public static void Main(string[] args)
{
listener = new TcpConnectionListener(IPAddress.Any, 4296);
listener.NewConnection += NewConnectionHandler;
Console.WriteLine("Starting server!");
listener.Start();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
listener.Close();
}
static void NewConnectionHandler(object sender, NewConnectionEventArgs args)
{
Console.WriteLine("New connection from " + args.Connection.EndPoint.ToString();
args.Connection.DataReceived += DataReceivedHandler;
args.Recycle();
}
private static void DataReceivedHandler(object sender, DataEventArgs args)
{
Connection connection = (Connection)sender;
Console.WriteLine("Received (" + string.Join<byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString());
connection.SendBytes(args.Bytes, args.SendOption);
args.Recycle();
}
}
}
Client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hazel;
using Hazel.Tcp;
namespace HazelExample
{
class ClientExample
{
static Connection connection;
public static void Main(string[] args)
{
NetworkEndPoint endPoint = new NetworkEndPoint("127.0.0.1", 4296);
connection = new TcpConnection(endPoint);
connection.DataReceived += DataReceived;
Console.WriteLine("Connecting!");
connection.Connect();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
connection.Close();
}
}
}
Disclaimer: this is my first foray into anything directly tcp/socket related. I've read -the- -following- -resources- and am trying to come up with a very simple test application.
I'm trying to develop a local server running with a TcpListener object. I can instantiate it fine and run netstat to see the port in the LISTENING state. However, I can't telnet or create a test client to connect manually. Telnet says simply that it could not open a connection. Trying a test client application throws the exception
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Additional information: Only one usage of each socket address (protocol/network address/port) is normally permitted
In this SO question, the asker ultimately resolved it via a faulty NIC. How might I look for that?
This leaves me puzzled. How do I ever test or connect to the server? Here's my code.
For the server:
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace TcpConsole
{
class Program
{
static void Main(string[] args)
{
var localPort = ConfigurationManager.AppSettings["localPort"];
var portNumber = int.Parse(localPort);
var maxConnections = ConfigurationManager.AppSettings["maxConnections"];
var maxConnectionsNumber = int.Parse(maxConnections);
Console.WriteLine("Preparing to start server on port {0}", portNumber);
Console.WriteLine("Max connections: {0}", maxConnectionsNumber);
var ipHostInfo = Dns.GetHostEntry("localhost");
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, portNumber);
Console.WriteLine("Starting server with local IP {0}", ipAddress);
var listener = new TcpListener(localEndPoint);
listener.Start(maxConnectionsNumber);
Console.WriteLine();
Console.WriteLine("Server started...");
Console.WriteLine();
while (true)
{
var socket = listener.AcceptSocket();
Task.Factory.StartNew(() =>
{
ProcessSocket(socket);
});
}
}
private static async void ProcessSocket(Socket socket)
{
try
{
using (var stream = new NetworkStream(socket))
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
var received = await reader.ReadToEndAsync();
Console.WriteLine("Received: " + received);
}
socket.Close();
socket.Dispose();
}
catch (Exception exception)
{
Console.WriteLine("There was an error processing a message.");
Console.WriteLine(exception);
}
}
}
}
Seeing the above code running:
For the test application:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace TcpConsoleClient
{
class Program
{
static void Main(string[] args)
{
var ipHostInfo = Dns.GetHostEntry("localhost");
var ipAddress = ipHostInfo.AddressList[0];
var remoteEndPoint = new IPEndPoint(ipAddress, 3245);
var client = new TcpClient(remoteEndPoint);
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream))
using (var writer = new StreamWriter(stream))
{
writer.AutoFlush = true;
string input;
while((input = Console.ReadLine()) != "exit")
{
writer.WriteLine(input);
}
}
}
}
}
A TCP/IP connection has a local IP address and port, as well as a remote IP address and port.
Generally, a port number can only be assigned to one socket at a time. The error message indicates that an attempt was made to associate more than one socket with the same port number.
The reason why can be found in the client code:
var client = new TcpClient(remoteEndPoint);
This overload of the TcpClient constructor accepts an IPEndPoint specifying the local endpoint. That is, when the TcpClient is constructed, it will get bound to the port number specified by remoteEndPoint, which fails, because that port number is already in use by the server application.
To fix this, use the parameter-less TcpClient constructor, and instead pass remoteEndPoint to the Connect call:
var client = new TcpClient();
client.Connect(remoteEndPoint);
I test those code independently working fine. Once I write it into user control and add it into application reference, and use it in the WPF, Visual studio turns to "Not Responding". This drives me crazy.
below is the user control code:
namespace ServerUserContorl
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public Socket server;
public Socket Command_Listening_Socket; //used to listen for connections for exchanging commands between server and mobile
public Socket Interaction_Listening_Socket1;// designed for receiving information from mobile
public Socket Interaction_Listening_Socket2;// designed for sending information to mobile
public Socket Interaction_Receiving_Socket;// receiving
public Socket Interaction_Sending_Socket;// sending
public UserControl1()
{
IPAddress local = IPAddress.Parse("134.129.125.126");
IPEndPoint iepCommand = new IPEndPoint(local, 8080);// IP end point for command listening socket
IPEndPoint iepReceiving = new IPEndPoint(local, 8090);// IP end point for receiving socket
IPEndPoint iepSending = new IPEndPoint(local, 9090);// Ip end point for sending socket
//part for command listening socket connection
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(iepCommand);
server.Listen(20);
// part for receiving Socket
Interaction_Listening_Socket1 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Interaction_Listening_Socket1.Bind(iepReceiving);
Interaction_Listening_Socket1.Listen(20);
// part for sending Socket
Interaction_Listening_Socket2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Interaction_Listening_Socket2.Bind(iepSending);
Interaction_Listening_Socket2.Listen(20);
while (true)
{
// Here is three blocks for accepting the new client,
// once client connect to the command listening socket,
// pass the command listening socket to the threadService class
// and start a thread for receiving the userID
Command_Listening_Socket = server.Accept();
Interaction_Receiving_Socket = Interaction_Listening_Socket1.Accept();
Interaction_Sending_Socket = Interaction_Listening_Socket2.Accept();
threadService service = new threadService(Command_Listening_Socket,Interaction_Receiving_Socket,Interaction_Sending_Socket);
Thread userCommand = new Thread(service.userCommand);
userCommand.Start();
Debug.WriteLine("thread starts");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Diagnostics;
using System.Threading;
namespace ServerUserContorl
{
class CommunicationThread
{
public Socket Interaction_Receiving_Socket, Interaction_Sending_Socket;
public CommunicationThread(Socket receiving, Socket sending)
{
Interaction_Receiving_Socket = receiving;
Interaction_Sending_Socket = sending;
}
// connect with iep2 9090, clientCom1,clientCommunication1
public void sendThread()
{
Debug.WriteLine("In the SendThread method");
byte[] bytes = new byte[1024];
string greeting = "hello, this is the message from the server.";
bytes = System.Text.Encoding.ASCII.GetBytes(greeting);
Debug.WriteLine("the byte is " + bytes);
int i = 0;
while (i < 10)
{
Interaction_Sending_Socket.Send(bytes);
Thread.Sleep(1000);
i++;
}
Debug.WriteLine("send is successful");
// clientCommunication1.Close();
}
//8080
public void receiveThread()
{
int i = 0;
string data = null;
Debug.WriteLine("In the receive method");
byte[] bytes = new byte[1024];
while ((i = Interaction_Receiving_Socket.Receive(bytes)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Debug.WriteLine("receive from the client " + data);
}
//clientCommunication.Close();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Threading;
namespace ServerUserContorl
{
class threadService
{
public Socket client;
//public Socket clientCommunication;
public string status;
public Socket Interaction_Receiving_Socket, Interaction_Sending_Socket;
public static int connections = 0;
int i = 0;
public threadService(Socket client,Socket receiving, Socket sending)
{
this.client = client;
Interaction_Receiving_Socket = receiving;
Interaction_Sending_Socket = sending;
}
public void userCommand()
{
string data = null;
byte[] bytes = new byte[1024];
if (client != null)
{
connections++;
}
Debug.WriteLine("new client connects, {0} connections", connections);
while ((i = client.Receive(bytes)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
status = data;
Debug.WriteLine("receive from client: " + status);
if (status == "1")
{
CommunicationThread communication = new CommunicationThread(Interaction_Receiving_Socket,Interaction_Sending_Socket);
Thread newSendThread = new Thread(communication.sendThread);
newSendThread.Start();
Debug.WriteLine("start the communication thread--status 1");
// CommunicationThread communication = new CommunicationThread();
Thread newReceiveThread = new Thread(communication.receiveThread);
newReceiveThread.Start();
Debug.WriteLine("start the communication thread--status 2");
}
}
}
}
}
In the WFP, I only add it:
xmlns:myControl="clr-namespace:ServerUserContorl;assembly=ServerUserContorl"
<myControl:UserControl1>
Visual Studio's Designer has to call the control's constructor when you add the control, which means the Designer is going into the while(true) loop in the constructor.
First: Do not put an infinite loop in your control's constructor. EVER. If you need something to poll endlessly, that should be handled in your program's main or, better yet, in a separate thread. Until the constructor finishes the control can't be referenced by other objects, so you need to let the constructor finish.
Second: If you have code in your constructor you want the Designer to skip, you can do this:
using System.ComponentModel;
public MyControl()
{
// code that Designer should run
if (LicenseManager.UsageMode == LicenseUsageMode.DesignTime)
return;
// code that Designer should not run
}
I found this great code on MSDN for a UDP Client/Server connection, however the client can only send to the server, it cant reply back. How can I make this so the server can respond to the client that send the message.
The Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security.Cryptography;
namespace UDP_Server
{
class Program
{
private const int listenPort = 11000;
private static void StartListener()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
try
{
while (!done)
{
Console.WriteLine("Waiting for broadcast");
byte[] bytes = listener.Receive(ref groupEP);
Console.WriteLine("Received broadcast from {0} :\n {1}\n",groupEP.ToString(), Encoding.ASCII.GetString(bytes, 0, bytes.Length));
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
listener.Close();
}
}
public static int Main()
{
StartListener();
return 0;
}
}
}
And the client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Security.Cryptography;
namespace UDP_Client
{
class Program
{
static void Main(string[] args)
{
Send("TEST STRING");
Console.Read();
}
static void Send(string Message)
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress broadcast = IPAddress.Parse("10.1.10.117");
byte[] sendbuf = Encoding.ASCII.GetBytes(Message);
IPEndPoint ep = new IPEndPoint(broadcast, 11000);
s.SendTo(sendbuf, ep);
}
}
}
Just do it the other way round. Call StartListener on the client and it can receive udp data like a server.
On your server just send data with the clients code.
It's the same code, just with reversed roles. The client needs to listen on some port, and the server sends the message to the client's endpoint instead of the broadcast address.