I am creating a server-client application where the server and client can talk to each other.
When I call the start method on the server, i get an error saying this:
Only one usage of each socket address (protocol/network address/port) is normally permitted
Here is Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace NetworkingTest {
class Program {
static void Main(string[] args) {
bool readLine = true;
string input = "";
while (true) {
if (readLine == true) {
input = Console.ReadLine();
}
if (input == "server") {
Server server = new Server(IPAddress.Any, 12346);
readLine = false;
}
if (input == "client") {
Client client = new Client(IPAddress.Parse("myipv4"), 12346);
readLine = false;
}
}
}
}
}
Here is Server.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace NetworkingTest {
class Server {
public TcpListener server;
public Server (IPAddress ip, int port) {
server = new TcpListener(ip, port);
server.Start();
Thread serverRunThread = new Thread(new ThreadStart(RunServer));
serverRunThread.Start();
}
void RunServer () {
while (true) {
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Client connected!");
Thread serverHandlerThread = new Thread(new ParameterizedThreadStart(HandleClient));
serverHandlerThread.Start(client);
}
}
void HandleClient(object c) {
TcpClient client = (TcpClient)c;
NetworkStream stream = client.GetStream();
int i;
string data = null;
byte[] bytes = new byte[256];
while((i = stream.Read(bytes, 0, bytes.Length)) != 0) {
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: " + data);
}
stream.Close();
client.Close();
}
}
}
And here is Client.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace NetworkingTest {
class Client {
public TcpClient client;
public Client (IPAddress ip, int port) {
client = new TcpClient();
client.Connect(ip, port);
Thread thread = new Thread(new ThreadStart(ConnectToServer));
thread.Start();
}
void ConnectToServer () {
while (true) {
string input = Console.ReadLine();
if (input == "exit" || input == "quit" || input == "close") {
break;
} else {
SendMessageToServer(input);
}
}
}
void SendMessageToServer (string message) {
NetworkStream stream = client.GetStream();
byte[] bytes = Encoding.ASCII.GetBytes(message);
stream.Write(bytes, 0, bytes.Length);
stream.Close();
}
}
}
EDIT:
There was a problem in Program.cs, fixed while loop:
while (readLine == true) {
input = Console.ReadLine();
if (input == "server") {
Server server = new Server(IPAddress.Any, 12346);
readLine = false;
}
if (input == "client") {
Client client = new Client(IPAddress.Parse("10.0.0.5"), 12346);
readLine = false;
}
}
That happens because of the error in your while(true) loop. First you ask user for a line with Console.ReadLine(). If input is "server" you start your server, BUT then you go to the beginning of your while loop and your readLine variable is false, and input is still "server", so it creates second server (basically you have infinite loop). Since you already have one sever on this port - second try fails with the error you see.
To fix, remove while loop, or do it more correctly, like this:
static void Main(string[] args) {
while (true) {
Console.WriteLine("Type \"server\" to start server, type \"client\" to start client, type \"exit\" to exit");
string input = Console.ReadLine();
if (input == "server") {
Server server = new Server(IPAddress.Any, 12346);
}
else if (input == "client") {
Client client = new Client(IPAddress.Parse("myipv4"), 12346);
}
else if (input == "exit")
return;
}
}
Related
Currently, I'm programming in C#, I would like to modify the code below to isolate one client connection. so like creating a break-out room from the main pool.
Below are 2 files, one is just the basic standard .NET Framework Console App Program.cs file; the other is the server file. Combined, they both can make a multi-threaded server, but I would like one that allows me to also select a client to connect to in case if I were to create a remote control application as my friend did.
On a side note, I would like to share that I want to be able to connect to a client by entering connect [1,2,3,etc..] into the console.
Answers
If you answer, please put some code, It would really, really help. I learn a lot better by looking att the code rather than reading documentation.
Code
Server.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace TCPServer
{
class Server
{
TcpListener server = null;
int counter = 0;
public Server(string ip, int port)
{
IPAddress localAddr = IPAddress.Parse(ip);
server = new TcpListener(localAddr, port);
server.Start();
StartListener();
}
public void StartListener()
{
try
{
while (true)
{
Console.WriteLine("Waiting for incoming connections...");
TcpClient client = server.AcceptTcpClient();
counter += 1;
Console.WriteLine("Connected to authorized client: {0}", counter);
Thread t = new Thread(new ParameterizedThreadStart(HandleDeivce));
t.Start(client);
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
server.Stop();
}
}
public void HandleDeivce(Object obj)
{
TcpClient client = (TcpClient)obj;
var stream = client.GetStream();
string imei = String.Empty;
string data = null;
Byte[] bytes = new Byte[256];
int i;
try
{
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
string hex = BitConverter.ToString(bytes);
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("{1}: Received: {0}", data, Thread.CurrentThread.ManagedThreadId);
if (data != "auth token")
{
stream.Close();
client.Close();
}
string str = "Device authorization successfull";
Byte[] reply = System.Text.Encoding.ASCII.GetBytes(str);
stream.Write(reply, 0, reply.Length);
Console.WriteLine("{1}: Sent: {0}", str, Thread.CurrentThread.ManagedThreadId);
}
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.ToString());
client.Close();
}
}
}
}
Program.cs
using System;
using System.Threading;
namespace TCPServer
{
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(delegate()
{
Server server = new Server("127.0.0.1", 13000);
});
thread.Start();
Console.WriteLine("Server started...");
}
}
}
Take a look at the following two programs:
//Server
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace MyServerProgram
{
class Program
{
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
int port = 2000;
TcpListener listener = new TcpListener(ip, port);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream netStream = client.GetStream();
BinaryReader br = new BinaryReader(netStream);
try
{
while (client.Client.Connected)
{
string str = br.ReadString();
Console.WriteLine(str);
}
}
catch
{
br.Close();
netStream.Close();
client.Close();
listener.Stop();
}
}
}
}
//Client
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace MyClientProgram
{
class Program
{
static void Main(string[] args)
{
int port = 2000;
TcpClient client = new TcpClient("localhost", port);
NetworkStream netStream = client.GetStream();
BinaryWriter br = new BinaryWriter(netStream);
try
{
int i=1;
while (client.Client.Connected)
{
br.Write(i.ToString());
br.Flush();
i++;
int milliseconds = 2000;
System.Threading.Thread.Sleep(milliseconds);
}
}
catch
{
br.Close();
netStream.Close();
client.Close();
}
}
}
}
These programs are working fine.
Suppose, at this point of this program, I need the server to print a message on the screen as soon as a client gets connected to it, and, also when the client is disconnected.
How can I do that?
AcceptTcpClient blocks execution and starts waiting for connection. So right after it you can write message that client connected. Also you could write connected client address. Just for information, but sometimes it could be helpful.
TcpClient client = listener.AcceptTcpClient();
ShowMessage("Connected " + ((IPEndPoint)client.Client.RemoteEndPoint).Address);
For detect client disconnect you could catch exceptions. Change your catch like this:
catch (Exception ex) {
var inner = ex.InnerException as SocketException;
if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
ShowMessage("Disconnected");
else
ShowMessage(ex.Message);
...
I try to make the LAN chat application, use Send() and Receive() function in C# to send and receive message. But the problem is that, when user type in message into Console and press Enter keyboard, this content suddenly appear in Console Screen before WriteLine my form appear (For example: what I expected is You: hello)
How could I remove line "hello". What I expecting is:
Client: hi
You: hello
Code for Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace SimpleTcpSrvr
{
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
int recv;
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"),9050);
Socket newsock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",clientep.Address,clientep.Port);
string welcome = "Welcome to my test server";
data = Encoding.UTF8.GetBytes(welcome);
client.Send(data,data.Length,SocketFlags.None);
string input;
while (true)
{
data = new byte[1024];
recv = client.Receive(data);
if (recv == 0)
break;
Console.WriteLine("Client: "+Encoding.UTF8.GetString(data, 0, recv));
input = Console.ReadLine();
Console.WriteLine("You: " + input);
client.Send(Encoding.UTF8.GetBytes(input));
}
Console.WriteLine("Disconnected from {0}", clientep.Address);
client.Close();
newsock.Close();
Console.ReadLine();
}
}
}
Code for Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace SimpleTcpClient
{
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.UTF8;
byte[] data = new byte[1024];
string input, stringData;
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"),9050);
Socket server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch(SocketException e)
{
Console.WriteLine("Unable to connect to server.");
Console.WriteLine(e.ToString());
return;
}
int recv = server.Receive(data);
stringData = Encoding.UTF8.GetString(data, 0, recv);
Console.WriteLine(stringData);
while (true)
{
input = Console.ReadLine();
if (input == "exit")
break;
Console.WriteLine("You: " + input);
server.Send(Encoding.UTF8.GetBytes(input));
data = new byte[1024];
recv = server.Receive(data);
stringData = Encoding.UTF8.GetString(data, 0, recv);
byte[] utf8string = System.Text.Encoding.UTF8.GetBytes(stringData);
Console.WriteLine("Server: "+stringData);
}
Console.WriteLine("Disconnecting from server...");
server.Shutdown(SocketShutdown.Both);
server.Close();
Console.WriteLine("Disconnected!");
Console.ReadLine();
}
}
}
Thanks everyone!
You could try this, Set the cursor position back to the start of the previous line after ReadLine & then overwrite the line with your text - in your case as you are prepending "You: " your output string will be longer than the input string - if it were smaller you could overwrite with spaces to clear any excess characters.
input = Console.ReadLine();
Console.SetCursorPosition(0, Console.CursorTop-1);
Console.WriteLine("You: " + input);
EDIT
With all great functionality that NetworkCommsDotNet offers, it looks like this library is not actively supported anymore. I am changing direction to accept Eser's response as answer. I tested the provided code and it worked. Thanks for your help.
Below is my code of simple TCP client-server, based on NetworkCommsDotNet library. The client periodically sends changing positions of an "object" to the server, and the server displays them. This works fine, however, what I want to achieve is exactly the opposite: I want the client to only connect to the server, and once the server detects a connection, then it starts periodically sending some X and Y coordinates back to the client. I could not have this done with NetworkCommsDotNet, any help is appreciated.
Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetworkCommsDotNet;
using NetworkCommsDotNet.Connections.TCP;
namespace ObjectPositionClient
{
class Program
{
static void Main(string[] args)
{
try {
var conn = TCPConnection.GetConnection(new ConnectionInfo("127.0.0.1", 50747));
System.Timers.Timer tmer;
tmer = new System.Timers.Timer(3000);
tmer.Elapsed += (sender, e) => TimerElapsed(sender, e, conn);
tmer.Enabled = true;
Console.WriteLine("Press any key to exit client.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
catch (Exception e)
{
Console.WriteLine(e.InnerException + "\n" + e.Message);
}
}
static public void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e, TCPConnection conn)
{
Random rnd = new Random();
int X = rnd.Next(1, 101);
int Y = rnd.Next(1, 51);
conn.SendObject("Message", "X=" + X + "; Y=" + Y);
}
}
}
Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NetworkCommsDotNet;
using NetworkCommsDotNet.Connections;
namespace ObjectPositionServer
{
class Program
{
static void Main(string[] args)
{
try
{
var con = Connection.StartListening(ConnectionType.TCP, new System.Net.IPEndPoint(System.Net.IPAddress.Any, 50747));
NetworkComms.AppendGlobalIncomingPacketHandler<string>("Message", PrintIncomingMessage);
Console.WriteLine("Server ready. Press any key to shutdown.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
catch (Exception e)
{
Console.WriteLine(e.InnerException + "\n" + e.Message);
}
}
private static void PrintIncomingMessage(PacketHeader header, Connection
connection, string message)
{
Console.WriteLine(message + "\n");
}
}
}
Here is a TCP based, basic, client/server sample. Whenever a client connects to server, server sends 10 strings to client and then close the connection. I think this is similar to your case.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
public class TCPTest
{
public static void StartAll()
{
Task.Run(() => StartServer());
Task.Run(() => StartClient());
}
static void StartServer()
{
TcpListener listener = new TcpListener(IPAddress.Any, 12345);
listener.Start();
Console.WriteLine("Server Started");
while (true)
{
var client = listener.AcceptTcpClient();
Console.WriteLine("A new client is connected");
ThreadPool.QueueUserWorkItem(ServerTask,client);
}
}
static void ServerTask(object o)
{
using (var tcpClient = (TcpClient)o)
{
var stream = tcpClient.GetStream();
var writer = new StreamWriter(stream);
for (int i = 0; i < 10; i++)
{
writer.WriteLine($"packet #{i + 1}");
writer.Flush();
Thread.Sleep(1000);
}
Console.WriteLine("Server session ended..");
}
}
static void StartClient()
{
TcpClient client = new TcpClient();
client.Connect("localhost", 12345);
var stream = client.GetStream();
var reader = new StreamReader(stream);
string line = "";
while((line = reader.ReadLine()) != null)
{
Console.WriteLine("Client received: "+ line);
}
Console.WriteLine("Client detected end of the session");
}
}
Use TCPTest.StartAll(); to start the test.
You can even telnet to this server. telnet localhost 12345
EDIT
Since you have commented, you want to transfer objects between client and server, I modified to code to show how it can be done (using Json.Net). This time, server sends 10 User objects to client.
I will post it as a new code, in case someone wants to see the minor differences.
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
public class TCPTest
{
//Sample class to transfer between server and client
public class User
{
public string Name { get; set; }
public int Id { get; set; }
public DateTime BirthDate { set; get; }
}
public static void StartAll()
{
Task.Run(() => StartServer());
Task.Run(() => StartClient());
}
static void StartServer()
{
TcpListener listener = new TcpListener(IPAddress.Any, 12345);
listener.Start();
Console.WriteLine("Server Started");
while (true)
{
var client = listener.AcceptTcpClient();
Console.WriteLine("A new client is connected");
ThreadPool.QueueUserWorkItem(ServerTask, client);
}
}
static void ServerTask(object o)
{
using (var tcpClient = (TcpClient)o)
{
var stream = tcpClient.GetStream();
var writer = new StreamWriter(stream);
for (int i = 0; i < 10; i++)
{
var user = new User() { Name = $"Joe{i}", Id = i , BirthDate = DateTime.Now.AddDays(-10000)};
var json = JsonConvert.SerializeObject(user);
writer.WriteLine(json);
writer.Flush();
Thread.Sleep(1000);
}
Console.WriteLine("Server session ended..");
}
}
static void StartClient()
{
TcpClient client = new TcpClient();
client.Connect("localhost", 12345);
var stream = client.GetStream();
var reader = new StreamReader(stream);
string json = "";
while ((json = reader.ReadLine()) != null)
{
var user = JsonConvert.DeserializeObject<User>(json);
Console.WriteLine($"Client received: Name={user.Name} Id={user.Id} BirthDate={user.BirthDate}");
}
Console.WriteLine("Client detected end of the session");
}
}
I'm using HigLabo to create an email client. Also I need to use an http proxy.
But authentication fails every time.
I found the base code here : .net pop3 over http proxy
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HigLabo.Net;
using HigLabo.Net.Pop3;
using System.Net.Sockets;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static Pop3Client pop;
static Socket socket;
static void Main(string[] args)
{
String proxyAddr = "112.241.212.104"; //This seemed to be working
int proxyPort = 8585;
byte[] buffer = new byte[25];
pop = new Pop3Client("PopClient");
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
Console.WriteLine("Connecting to proxy...");
socket.Connect(proxyAddr, proxyPort);
Console.WriteLine("Connected to proxy");
Console.WriteLine("Sending Packets...");
socket.Send(Encoding.UTF8.GetBytes("CONNECT pop.mail.yahoo.com:995 HTTP/1.1<CR><LF>"));
socket.Send(Encoding.UTF8.GetBytes("<CR><LF>"));
Console.WriteLine("Packets sent");
Console.WriteLine("Waiting for response...");
socket.Receive(buffer);
Console.WriteLine("Packets received");
Console.WriteLine("Time Elapsed : " + timeElapsed + " seconds");
Console.WriteLine("Connectong POP to socket...");
if (pop.Connect(socket))
{
pop.Connect();
Console.WriteLine("Connection completed");
}
else
{
Console.WriteLine("Disconnected");
Disconnect();
return;
}
pop.Ssl = true;
pop.UserName = "EMAIL_ADDRESS";
pop.Password = "PASSWORD";
pop.ServerName = "pop.gmail.com";
pop.Port = 995;
Console.WriteLine("Authenticating...");
if (pop.Authenticate())
{
Console.WriteLine("Authentication completed"); //Never comes here
GetMail();
}
else
{
Console.WriteLine("Authentication failed"); //Always comes here
Disconnect();
}
}
private static void GetMail()
{
HigLabo.Mime.MailMessage msg = pop.GetMessage(1);
Console.WriteLine(msg.BodyText);
}
static void Disconnect()
{
Console.WriteLine("Disconnecting...");
pop.Close();
socket.Close();
Console.WriteLine("Disconnected");
}
}
}
I gave permission for the app also.
What is wrong here?
Are there any other/better/easy ways to do this? May be with a different library?
This is wrong: <CR><LF>.
What you want to use is \r\n in your strings.