I have a client and a server that communicates in a network using TCP/IP protocol. Whenever I start the application in Visual Studio. I have a button StartListening that starts the server and listen the client requests.
Now I'm trying to create that StartListening button into a Window Service and don't need to click on the button for listening.
Here is a server code:
protected override void OnStart(string[] args)
{
Thread thread = new Thread(StartListening);
}
public void StartListening()
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
int nPort = 8001;
TcpListener tcpListener = new TcpListener(ipAddress,nPort);
tcpListener.Start();
byte[] bytes = new byte[256];
while (true)
{
Socket socket = tcpListener.AcceptSocket();
int res = socket.Receive(bytes);
ASCIIEncoding asen = new ASCIIEncoding();
string str = asen.GetString(bytes);
//logic
socket.Close();
}
}
Note: In //logic in above code what thing I should place to communicate server with clients?
I think two threads not working because while True is thread and Actually two threads not work in the same time here is code may be fix your problem
Thread thread = new Thread(new ThreadStart(//Your method name here));
thread.start();
To reply to your client: socket.Send(asen.GetBytes("reply"));
Related
I'm working to make a Client/Server Application in C# using winsock Control. I done every thing in that but i stuck the place of sending data from client to server. In my program server always listen the client using the ip and port. I send the data from the client to server.
1)When click the Listen button on the server form it open the server where client is connect.
2)In Client form 1st i click the connect button for that the server is connected Gives an message (Connect Event: ip) for this message we easly know that the client is connected to the server.
3)Then we enter some data in the Send Data text Box then click Send Button to send the data to server and also save in client.
Code Below:
SERVER:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
const string DEFAULT_SERVER = "ip";
const int DEFAULT_PORT = 120;
System.Net.Sockets.Socket serverSocket;
System.Net.Sockets.SocketInformation serverSocketInfo;
public string Startup()
{
IPHostEntry hostInfo = Dns.GetHostByName(DEFAULT_SERVER);
IPAddress serverAddr = hostInfo.AddressList[0];
var serverEndPoint = new IPEndPoint(serverAddr, DEFAULT_PORT);
serverSocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
serverSocket.Bind(serverEndPoint);
return serverSocket.LocalEndPoint.ToString();
}
public string Listen()
{
int backlog = 0;
try
{
serverSocket.Listen(backlog);
return "Server listening";
}
catch (Exception ex)
{
return "Failed to listen" + ex.ToString();
}
}
public string ReceiveData()
{
System.Net.Sockets.Socket receiveSocket;
byte[] buffer = new byte[256];
receiveSocket = serverSocket.Accept();
var bytesrecd = receiveSocket.Receive(buffer);
receiveSocket.Close();
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
return encoding.GetString(buffer);
}
private void Listen_Click(object sender, EventArgs e)
{
string serverInfo = Startup();
textBox1.Text = "Server started at:" + serverInfo;
serverInfo = Listen();
textBox1.Text = serverInfo;
//string datatosend = Console.ReadLine();
//SendData(datatosend);
serverInfo = ReceiveData();
textBox1.Text = serverInfo;
//Console.ReadLine();
}
private void winsock_DataArrival(object sender, AxMSWinsockLib.DMSWinsockControlEvents_DataArrivalEvent e)
{
ReceiveData();
Listen();
}
private void winsock_ConnectEvent(object sender, EventArgs e)
{
Listen();
}
}
}
This all are work perfectly But here my problem is that i get data form the client to server at only one time. When i send data again from the client to the server its not working and gives me some Message like
Additional information: Only one usage of each socket address
(protocol/network address/port) is normally permitted
In the server form
serverSocket.Bind(serverEndPoint);
Please someone help me to solve my problem.
Thank you.
Try this. It helps you
delegate void AddTextCallback(string text);
public Form1()
{
InitializeComponent();
}
private void ButtonConnected_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ServerHandler));
}
private void ServerHandler(object state)
{
TcpListener _listner = new TcpListener(IPAddress.Parse("12.2.54.658"), 145);
_listner.Start();
AddText("Server started - Listening on port 145");
Socket _sock = _listner.AcceptSocket();
//AddText("User from IP " + _sock.RemoteEndPoint);
while (_sock.Connected)
{
byte[] _Buffer = new byte[1024];
int _DataReceived = _sock.Receive(_Buffer);
if (_DataReceived == 0)
{
break;
}
AddText("Message Received...");
string _Message = Encoding.ASCII.GetString(_Buffer);
AddText(_Message);
}
_sock.Close();
AddText("Client Disconnected.");
_listner.Stop();
AddText("Server Stop.");
}
private void AddText(string text)
{
if (this.listBox1.InvokeRequired)
{
AddTextCallback d = new AddTextCallback(AddText);
this.Invoke(d, new object[] { text });
}
else
{
this.listBox1.Items.Add(text);
}
}
I'm also have the same problem like you on last month but i solve that using this Receive multiple different messages TcpListener C# from stackoverflow. This helps me lot hope it helps to solve your problem also.
I'm not 100% sure you understand TCP sockets so here goes.
When you use a TCP listener socket you first bind to a port so that clients have a fixed, known point to connect to. This reserves the port for your socket until you give it up by calling Close() on that socket.
Next you Listen in order to begin the process of accepting clients on the port you bound to. You can do both this and the first step in one but as you haven't I haven't here.
Next you call Accept(). This blocks (halts execution) until a client connects and then it returns a socket which is dedicated to communication with that client. If you want to allow another client to connect, you have to call Accept() again.
You can then communicate with your client using the socket that was returned by Accept() until you're done, at which point you call Close() on that socket.
When you're done listening for new connections you call Close() on your listener socket.
However when you press your listen button the following happens:
You bind correctly, you begin listening correctly and then your call to ReceiveData() blocks on the Accept call until a client is received. You then receive some data (though this is TCP so that might not be the whole data!) and then you instantly close the connection to your client.
I presume to get the error you're getting you must then press listen again on your server. This therefore restarts the whole listener socket and when you get to bind to the port the second time your previous listener is still bound to it and thus the call fails because something's already allocated on that port.
Solution wise you need to keep the socket returned from the Accept() call open until you're done with it. Have the client handle the close by calling the Shutdown() method on their socket or establish some convention for marking the end of communication.
You're also going to run into trouble when you try and have multiple users connected and so at some point you're either going to require threads or some asynchronous sockets but I feel that's out the scope of this question.
I suggest you do not use AxMSWinsockLib.. Have a look at socket example given here where it shows how to create a client socket and server socket - https://msdn.microsoft.com/en-us/library/kb5kfec7(v=vs.110).aspx AND this one - https://msdn.microsoft.com/en-us/library/6y0e13d3(v=vs.110).aspx
I seem to be having a hard time figuring out how to get my client app to automatically connect to a server app running on a separate machine on my LAN.
Right now the only way I'm able to get the client to connect to the server is by manually specifying the server's IP address in code:
private TcpClient client = new TcpClient();
private IPEndPoint serverEndPoint = neIPEndPoint(IPAddress.Parse("Server IP address goes here"), 8888);
My server app uses a TCP Listener, so I figured my client could do something similar, to be able to find the server, but I can't figure out how to implement it in code.
Code from my server app for finding the client to connect to:
private TcpListener tcpListener;
private Thread listenThread;
private int connectedClients = 0;
private delegate void WriteMessageDelegate(string msg);
public Form1()
{
InitializeComponent();
Server();
}
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
I've tried using a TextBox that the user can manually enter their server's IP address into (since they wouldn't have access to the code), but I think an automatic connection would be much more user friendly, especially since I don't know how to permanently save the user's server IP address if they use the above method of setting the IP for the client to connect to.
So, my question is: What would be the best method for me to enable my client to automatically connect to a server running on my LAN?
Thanks,
Patrick
UPDATE
I tried implementing the code for a UDP broadcast, but I can't seem to get it working.
Here is what I've added to my client (Along with the client code I had in there before):
public partial class Console : Form
{
//FIND SERVER
private void FindServer()
{
var Client = new UdpClient();
var RequestData = Encoding.ASCII.GetBytes("SomeRequestData");
var ServerEp = new IPEndPoint(IPAddress.Any, 0);
Client.EnableBroadcast = true;
Client.Send(RequestData, RequestData.Length, new IPEndPoint(IPAddress.Broadcast, 8888));
var ServerResponseData = Client.Receive(ref ServerEp);
var ServerResponse = Encoding.ASCII.GetString(ServerResponseData);
Console.WriteLine("Recived {0} from {1}", ServerResponse, ServerEp.Address.ToString());
Client.Close();
}
// SEND MESSAGES TO SERVER (VIA USER INTERACTION)
private TcpClient client = new TcpClient();
private IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("My IP Address was here (I tried changing it to "broadcast" as well"), 8888);
public Console()
{
InitializeComponent();
client.Connect(serverEndPoint);
}
private void SendMessage(string msg)
{
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
Here is what I've added to my server code:
private void BroadcastToClients()
{
var Server = new UdpClient(8888);
var ResponseData = Encoding.ASCII.GetBytes("SomeResponseData");
while (true)
{
var ClientEp = new IPEndPoint(IPAddress.Any, 0);
var ClientRequestData = Server.Receive(ref ClientEp);
var ClientRequest = Encoding.ASCII.GetString(ClientRequestData);
Console.WriteLine("Recived {0} from {1}, sending response", ClientRequest, ClientEp.Address.ToString());
Server.Send(ResponseData, ResponseData.Length, ClientEp);
}
}
I'd imagine there must be some conflicting code in there, but since I'm so new to this, I can't seem to figure it out...
UPDATE
I've still not managed to make any progress on this. Anyone out there that might be able to chime in and help me figure out why this isn't working for me?
Your client app can send a broadcast on the local subnet, on startup, 'asking for server'.
Your server will be listening for that message, and replies to the client.
Now the client knows the server's IP address and can start the TCP connection.
You have it here: C# How to do Network discovery using UDP Broadcast
I'm new with socket and trying to write a Client-Server application
My applicationhas those two main methods :
SERVER running on separate Thread :
public void socketListener()
{
byte[] StreamMessage = new byte[9632];
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEndPoint =new IPEndPoint(IPAddress.Any , ControlLayer.GlobalParam.PEER2PEER_PORT);
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
Socket Handler = listener.Accept();
//int ByteRec = Handler.Receive(StreamMessage);
int MessageLength;
MessageLength = Handler.Receive(StreamMessage, 0, StreamMessage.Length, SocketFlags.None);
//return MessageLength;
// string message = System.Text.Encoding.Default.GetString(StreamMessage);
string message = System.Text.Encoding.UTF8.GetString(StreamMessage);
OnDataRecievedFromRemotePeer(this, message, "TcpServer");//send data to screen
Task.Run(() => { ParseMessage(message, Handler); });
}
}
once data arrives I prase it collect data and send it using Client
CLIENT :
public void Write(string message)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(CreateClient), message);
}
private void CreateClient(object message)
{
try
{
peerClient = new TcpClient();
peerClient.Connect(remoteIP, 6001/*TODO remove this */);
netStream = peerClient.GetStream();//<- Exception
StreamWriter sw = new StreamWriter(netStream);
sw.Write((string)(message));
netStream.Close();
peerClient.Close();
}
catch(Exception ex)
{
//TODO :
}
}
Each station is symmetrical and have those two methods
I can tell that the server is working and accepting socket and data
but once I want to respond back I get exception in the Line marked in the CreateClient
stream was not writable and when looking on the netStream it is written that I have ObjectDisposed Exception .
What can be the cause of that ?
Also please inform me if more code is needed
You have a classical race here between the server closing the connection before the client has processed the response of the server.
TCP is a "polite" protocol, which means that you can not perform a fire and forget action on the server. The connection needs to be alive on both ends until both sides have processed all messages. Thus either the client needs to send an acknowledge/logout, so that the server can close the connection or at least the server has to wait x seconds until closing it.
I have a simple TCP server based on the TcpListener. Since I want to use it in a Windows Form application I made it run in a separate thread as follows:
public void Start() {
this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
this.serverThread.Name = "Tcp-Server";
this.serverThread.Start();
}
protected void ThreadProcess() {
try
{
IPAddress ipAd = IPAddress.Parse("169.254.42.86");
this.listener = new TcpListener(ipAd, this.port);
this.listener.Start();
Socket mySocket = this.listener.AcceptSocket();
while (true)
{
if (mySocket.Connected)
{
byte[] RecvBytes = new byte[8192];
int byteNo = mySocket.Receive(RecvBytes, RecvBytes.Length, 0);
ASCIIEncoding asen = new ASCIIEncoding();
mySocket.Send(asen.GetBytes("srv reply msg"));
}
else
{
WriteLine("socket not connected.");
}
}
}
finally {
StopListener();
}
}
If I use this server in a console application as:
static void Main(string[] args)
{
try
{
int port = 8001;
Server server = new Server(port);
server.Start();
while (true) {
//server is running in separate thread
}
...
everything works as expected. However, when I try to include it in a Windows-Form Application that starts the server when a button is clicked, the code doesn't work any more. The server thread is being launched, but it doesn't accept any sockets.
Is there something that I am missing? I have been searching high and low on google without result...
Thanks for any help!
Not really an answer but too much to type in the comments:
The easiest way to debug this issue is to simply call the ThreadProcess() method in the same thread:
public void Start() {
ThreadProcess();
//this.serverThread = new Thread(new ThreadStart(this.ThreadProcess));
//this.serverThread.Name = "Tcp-Server";
//this.serverThread.Start();
}
You can then step through your code to see what happens. As soon as you hit the this.listener.AcceptSocket(); line your application will block, but you should be able to connect to it.
Usually the problem is something silly everyone overlooks like the Start() method not being called.
Is it possible to identify an earlier UDP client without keeping the socket open? I want to link an integer ID to each unique client, but I don't want to keep any additional threads open.
//Receive (Server)
private static Int32 port = 11000;
private static UdpClient udpClient = new UdpClient(port);
public static void receive_threaded()
{
Thread t = new Thread(() =>
{
while (true)
{
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port);
byte[] content = udpClient.Receive(ref remoteIPEndPoint);
if (content.Length > 0)
{
string message = Encoding.UTF8.GetString(content);
if (action_message_receive != null) action_message_receive(String.Format("Recv({0}): {1}", remoteIPEndPoint.Port, message));
parseMessage(message);
}
}
});
t.Start();
}
//Send (Client)
private static void send_message(string ip, string message)
{
byte[] packetData = System.Text.UTF8Encoding.UTF8.GetBytes(message);
int port = 11000;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.SendTo(packetData, ep);
if (action_message_send != null) action_message_send("Send: " + message);
}
A client can request a (temporary) userID from the server, and the server will add it to it's database and notify the client when it's done doing that. However, I can't have the client send it's own userID when it's making requests because any memory altering application would mean a 'hacker' could gain access to other user's stuff.
Since the socket doesn't stay open, the IPEndPoint.Port changes every time the client sends something to the server, so I can't keep track of it with that. I could get it done by creating a username/pass on a userID request and having those sent on every single request involving the userID thereafter, but that would be silly.
So is there any way to do this without keeping a thread open for each client? I'm probably doing something really weird here because UDP is supposed to be a one way street, but I'm here to learn so I just had to ask.
You will need to introduce some sort of unique identifier chosen by the server and sent to the client for it to "behave and send it back for identification purposes". A random long integer should suffice.
UDP has neither connections nor identification/authentication mechanisms. If you want those, use TCP (but those can be bruteforced also...)