Send TCP data to specfic TcpClient in C# - c#

I'm getting an error that the TcpClient isn't connected and I can't send information to a socket that is not active. I'm wondering what's wrong with this code?
ERROR: This type of connection is not allowed on non-connected sockets.
SERVER:
public List<TcpClient> clients = new List<TcpClient>();
On client connection:
Socket s = currClient.Client;
clients.Add(currClient.Client);
When Sending Client Info
Stream sendData = clients[0].GetStream();
ASCIIEncoding text = new ASCIIEncoding();
byte[] clientInfoByte = text.GetBytes("msg");
sendData.Write(clientInfoByte, 0, clientInfoByte.Length);
sendData.Close();
CLIENT:
Thread thr = new Thread(commands);
thr.Start();
}
public static void commands()
{
Stream cmds = me.GetStream();
while (true)
{
byte[] b = new byte[100];
Socket s = me.Client;
int k = s.Receive(b);
string ClientInfo = "";
string command = System.Text.Encoding.ASCII.GetString(b);
if (command == "msg")
{
MessageBox.Show("Command Recieved!");
}
}
}

In your server create a TcpListener "listener" and accept incoming connections using:
listener.BeginAcceptTcpClient(
new AsyncCallback(DoAcceptTcpClientCallback),
listener);
Then in your callback you get your TcpClient to send data to
// Process the client connection.
public static void DoAcceptTcpClientCallback(IAsyncResult ar)
{
TcpListener listener = (TcpListener) ar.AsyncState;
TcpClient client = listener.EndAcceptTcpClient(ar);
//add to your client list
clients.Add(client);
}

Related

Tcp connection fails on LAN

I am trying to send a message from my laptop to my desktop over the LAN.
I have written a Tcp server that listens for a connection on a port, and a client that tries to connect to it and send a simple string as a message.
Server:
void Listen()
{
listener = new TcpListener(IPAddress.Any, port);
listener.Start();
while (true)
{
Debug.Log($"listening to {listener.LocalEndpoint}...");
var socket = listener.AcceptSocket();
Debug.Log("connected!");
var bytes = new byte[100];
int k = socket.Receive(bytes);
var data = Encoding.ASCII.GetString(bytes, 0, k);
Debug.Log(data);
socket.Send(new byte[] {1});
Debug.Log("responded");
socket.Close();
Debug.Log("closed connection");
}
}
Client:
public void Send()
{
client = new TcpClient();
Debug.Log("connecting...");
client.Connect("192.168.0.12", port);
Debug.Log("connected!");
var data = Encoding.ASCII.GetBytes("Hello!");
var stream = client.GetStream();
Debug.Log("sending data");
stream.Write(data, 0, data.Length);
Debug.Log("data sent! waiting for response...");
var reply = new byte[100];
stream.Read(reply,0,100);
Debug.Log("received response");
client.Close();
}
They communicate correctly when they are both on the same machine, but the client never connects to the server when I am running it on a different machine.
I have a rule in my firewall that allows an incoming connection through the port I have specified.
I have tried it with both computer's firewalls off and the connection still doesn't go through.
Any help would be greatly appreciated.

Why isn't my server responding to a client connecting TcpListener and TcpClient

So the way I start my server is like this
class GameServer
{
private TcpListener _server;
public void Run()
{
_server = new TcpListener(IPAddress.Any, Constants.Port);
_server.Start(Constants.Backlog);
while (true)
{
Console.WriteLine("Waiting for a connection... ");
//Perform a blocking call to accept requests.
_ = new GameClient(_server.AcceptTcpClient());
}
}
}
The idea here is that I want to seperate the Server from the Client connecting to the server.. So I'll have that class to accept GameClients where as the actual GameClient deals with the networkstream.
class GameClient
{
private TcpClient _client;
private NetworkStream _stream;
private byte[] buffer = new byte[Constants.BufferSize];
private Packet packet;
public GameClient(TcpClient client)
{
packet = new Packet();
_client = client;
Console.WriteLine($"[+] Client connected: {_client.Client.RemoteEndPoint}");
_stream = _client.GetStream();
}
}
I then connect with a client like so
public void Connect()
{
try
{
var client = new TcpClient(localEP: new IPEndPoint(
IPAddress.Parse(Constants.IpAddress),
Constants.Port));
client.Connect(remoteEP: new IPEndPoint(
IPAddress.Parse(Constants.IpAddress),
Constants.Port));
var stream = client.GetStream();
if (client.Connected)
{
Console.WriteLine("Connected to the server!");
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
And when I start the server, it says "Waiting for a connection... " and then I start the Client, and the client connects and it says "Connected to the server!" but the server never executes this line
Console.WriteLine($"[+] Client connected: {_client.Client.RemoteEndPoint}");
Why is that? And how do I properly make it execute that line?
You are giving to the TcpClient the same ip/port for the local endpoint and the remote endpoint:
var client = new TcpClient(localEP: new IPEndPoint(
IPAddress.Parse(Constants.IpAddress),
Constants.Port));
client.Connect(remoteEP: new IPEndPoint(
IPAddress.Parse(Constants.IpAddress),
Constants.Port));
That makes the socket to connect to itself (you can test it, send something using the stream and read from it, you will receive the message back). Just remove the local endpoint from the client and you will be good to go:
var client = new TcpClient();
client.Connect(remoteEP: new IPEndPoint(
IPAddress.Parse(Constants.IpAddress),
Constants.Port));

How I can to create python(or swift) TCP client for my TCP c# server?

How I can to create python(or swift) TCP client for my TCP c# server?
c# API for my TCP server:
Client client = Client();
bool Connect()
{
UserInfo userInfo = new UserInfo("login", "pass");
NetworkConnectionParam connectionParams = new NetworkConnectionParam("127.0.0.1", 4021);
try
{
client.Connect(connectionParams,userInfo,ClientInitFlags.Empty);
}
catch
{
return false;
}
return client.IsStarted;
}
I try it(python) :
import socket
sock = socket.socket()
sock.connect(('localhost', 4021))
But I don't uderstand how I must to send my login and password (like in API for c#).
I don`t undestand what you want to implement.
If you want to run Python code in C#, then look at this IronPython
If you want to implement TCP client in C#, then try smth like this:
using System.Net;
using System.Net.Sockets;
class Program
{
static int port = 8005; // your port
static void Main(string[] args)
{
// get address to run socket
var ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
// create socket
var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
// binding
listenSocket.Bind(ipPoint);
// start listen
listenSocket.Listen(10);
Console.WriteLine("Server is working");
while (true)
{
Socket handler = listenSocket.Accept();
// recieve message
StringBuilder builder = new StringBuilder();
int bytes = 0; // quantity of received bytes
byte[] data = new byte[256]; // data buffer
do
{
bytes = handler.Receive(data);
builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
}
while (handler.Available>0);
Console.WriteLine(DateTime.Now.ToShortTimeString() + ": " + builder.ToString());
// send response
string message = "your message recieved";
data = Encoding.Unicode.GetBytes(message);
handler.Send(data);
// close socket
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}

TcpClient/TcpServer/Listener, Server stops reading or client stops after 30 seconds

Client
class Client
{
public TcpClient client;
public StreamWriter server;
public ServerPlayer serverPlayer;
public Player player;
public void Connect(Player p)
{
player = p;
serverPlayer = new ServerPlayer();
client = new TcpClient(AddressFamily.InterNetwork);
client.Connect("Don't wory my IPV4 Is Here", 8888);
NetworkStream stream = client.GetStream();
server = new StreamWriter(stream);
Timer t = new Timer(Send, null, 0, 10);
}
public void Send(Object o)
{
server.WriteLine("Hello I am bob");
server.Flush();
}
}
Server
class TcpServerConnection
{
private static TcpListener tcpListener;
static void Main(string[] args)
{
tcpListener = new TcpListener(IPAddress.Any, 8888);
tcpListener.Start();
Console.WriteLine("Server started.");
while (true)
{
//blocks until a client has connected to the server
TcpClient client = tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private static void HandleClientComm(object client)
{
while (true)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
StreamReader server = new StreamReader(clientStream);
Console.WriteLine(server.ReadLine());
}
}
}
Problem
Track of events:
Started!
Hello I am bob
Hello I am bob
(Many Hello I am bobs later)
Hello I am bob
(Hello I am bobs just stopped)
(About 30 seconds)
Don't know if it because the client stops sending or server stops receiving or both!? But once this is ran about 30 seconds into this the server stops getting the send information. No error is thrown simply it just doesn't send.
Found out it was my internet. After my google-fu. I set my port for my server to be TCP open. Found out my router was getting suspicious after a spam of messages going into a random port. IP:IPV4 PORT:8888 SETTINGS:OPEN
Ok in your ServerConnection object the first while loop is fine. but the one in your handler is going to cause some problems try this:
private static void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
using(var stream = new StreamReader(clientStream))
{
while (stream.Peek() >= 0)
{
Console.WriteLine(server.ReadLine());
}
}
}
Since you are creating one and only one connection to the Server, and then sending messages constantly in the Client, accordingly when handling the client messages in the Server program, you should accept a TcpClient and then read messages in a loop, instead of accepting a Tcplient and reading a message all in a loop.
private static void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
StreamReader server = new StreamReader(clientStream);
while (true)
{
Console.WriteLine(server.ReadLine());
}
}

C# UDP Server/Client - NAT

Iam trying to send a message (via UDP) from my client to my server. The server should answer this message and if the client receives this answer he should print out a message.
If i run the client and server on my local network everything works fine.
If i try to connect through the internet from another PC outside my network the server receives the request of the client, sends an answer back, but the client never receives this answer. The client and the server are both behind a NAT but i portforwarded the ports at the server´s NAT and the server got its own DNS. I already tried NAT traversal but it gives me the same IP and port adress as the IPEndPoint of the server, after receiveing the request of the client, does.
I´ve got no idea how to fix this, so any guidance would be much appreciated.
Client
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
object[] oData = {1};
sendData(oData, 0,0, "Li");
while (true)
{
Console.ReadLine();
}
}
private void receiveData()
{
string receivePort = 8080;
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.ReceiveTimeout = 1000;
IPEndPoint end = new IPEndPoint(IPAddress.Any, receivePort);
client.Bind(end);
while (true)
{
try
{
byte[] data = new byte[1024];
client.Receive(data, 0, data.Length, SocketFlags.None);
object[] receivedObj = Deserialize(data);
string sType = (string)receivedObj[3];
if (sType == "Li")
{
console.WriteLine("received Li");
}
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
public static void sendData(object[] oData, int iFrom, int iTo, string sType)
{
string sendPort = 17171;
UdpClient client = new UdpClient();
string IP = "ThisIsTheDNSofmyServer.com"; //ServerDNS
//string IP = "192.168.xxx.xxx"; //serverIP in LAN
if (IP.StartsWith("T"))
{
IP = (Dns.GetHostAddresses(IP))[0].ToString();
}
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
oData[1] = iFrom;
oData[2] = iTo;
oData[3] = sType;
Byte[] data = Serialize(oData);
client.Send(data, data.Length, remoteEndPoint);
}
The server´s code is almost the same:
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
while (true)
{
Console.ReadLine();
}
}
private static void ReceiveData()
{
int receivePort = 17171;
UdpClient client = new UdpClient(receivePort);
while (true)
{
try
{
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = new byte[1024];
data = client.Receive(ref anyIP);
object[] receivedObj = Deserialize(data);
//if I receive data send an Answer
sendData(receivedObj, 0,0,"Li",anyIP.Address.ToString());
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
private static void sendData(object[] oData, int iFrom, int iTo, string sType, string IP)
{
int sendPort = 8080;
object[] paket = { oData, iFrom, iTo, sType };
UdpClient client = new UdpClient();
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
client.Send(data, data.Length, remoteEndPoint);
}
i believe this is a port cofniguration issue,
8080 is almost likely to be configured as alternate http
"The UdpClient you use to receive datagrams must be created using the multicast port number" from MSDN
Hope this helps and good luck
Krishna
You do not need to do anything unordinary to traverse NAT in the setup you described, you just need to send it from the server back to your client; specifically: you must send back to the end point, i.e. IP and port, you received it on.
client.Send(data, data.Length, remoteEndPoint); // remoteEndPoint is the IPEndPoint you got the datagram on

Categories