Creating C# TCP server - c#

I am trying to make a Server app and client app to connect through internet using C#.
Here is my Server app...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace Server
{
public partial class Form1 : Form
{
private byte[] data = new byte[1024];
private int size = 1024;
private Socket server;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.ControlBox = false;
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void button2_Click(object sender, EventArgs e)
{
server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(System.Net.IPAddress.Any, 8001);
server.Bind(iep);
server.Listen(1);
server.BeginAccept(new AsyncCallback(AcceptConn), server);
textBox1.Text = "Server Started!! \r\nWaiting for client...";
}
void AcceptConn(IAsyncResult iar)
{
Socket oldserver = (Socket)iar.AsyncState;
Socket client = oldserver.EndAccept(iar);
textBox1.Text = "Connected to: " + client.RemoteEndPoint.ToString();
string stringData = "Welcome to my server";
byte[] message1 = Encoding.ASCII.GetBytes(stringData);
client.BeginSend(message1, 0, message1.Length, SocketFlags.None,
new AsyncCallback(SendData), client);
}
void SendData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int sent = client.EndSend(iar);
client.BeginReceive(data, 0, size, SocketFlags.None,
new AsyncCallback(ReceiveData), client);
}
void ReceiveData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int recv = client.EndReceive(iar);
if (recv == 0)
{
client.Close();
textBox1.Text = "Waiting for client...";
server.BeginAccept(new AsyncCallback(AcceptConn), server);
return;
}
string receivedData = Encoding.ASCII.GetString(data, 0, recv);
listBox1.Items.Add(receivedData);
byte[] message2 = Encoding.ASCII.GetBytes(receivedData);
client.BeginSend(message2, 0, message2.Length, SocketFlags.None,
new AsyncCallback(SendData), client);
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
server.Close();
//server.Shutdown();
}
void ButtonStopOnClick(object obj, EventArgs ea)
{
Close();
}
}
}
And here is my Client app...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace Client
{
public partial class Form1 : Form
{
private TextBox newText;
private TextBox conStatus;
private ListBox results;
private Socket client;
private byte[] data = new byte[1024];
private int size = 1024;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.ControlBox = false;
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void button2_Click(object sender, EventArgs e)
{
textBox2.Text = "Connecting...";
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.0.3"), 8001);
//IPEndPoint iep = new IPEndPoint(IPAddress.Parse("41.232.217.55"), 8001);
newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
}
private void button3_Click(object sender, EventArgs e)
{
byte[] message = Encoding.ASCII.GetBytes(textBox1.Text);
textBox1.Clear();
client.BeginSend(message, 0, message.Length, SocketFlags.None,
new AsyncCallback(SendData), client);
}
private void button4_Click(object sender, EventArgs e)
{
client.Close();
textBox2.Text = "Disconnected";
}
void Connected(IAsyncResult iar)
{
client = (Socket)iar.AsyncState;
try
{
client.EndConnect(iar);
textBox2.Text = "Connected to: " + client.RemoteEndPoint.ToString();
client.BeginReceive(data, 0, size, SocketFlags.None,
new AsyncCallback(ReceiveData), client);
}
catch (SocketException)
{
textBox2.Text = "Error connecting";
}
}
void ReceiveData(IAsyncResult iar)
{
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceive(iar);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
listBox1.Items.Add(stringData);
}
void SendData(IAsyncResult iar)
{
Socket remote = (Socket)iar.AsyncState;
int sent = remote.EndSend(iar);
remote.BeginReceive(data, 0, size, SocketFlags.None,
new AsyncCallback(ReceiveData), remote);
}
}
}
I understand that the server app can use IPaddress.Any but the client must be specific to reach the server.
My problem is that i cant connect form another computer outside the local addressing (192.168.0.1, 192.168.0.2,....). I want the client to be able to connect to my server using my remote IP (41.232.217.55).

Related

Visual Studio 2017 C# Sockets UDP

Im having a hard time figuring this out.
I'm trying to make a chat where there's one server and multiple clients but I can't seem to get it to work.
Im using Visual Studio 2017 and it's a Windows Forms App .NET Framework project. Now, it works but only 2 clients can connect to each other. If I try to connect two users to one, one gets blocked out of the conversation and can't recive messages from the server.
To the question: Is it possible to make a server that many clients can connect to and the server can send messages to all connected clients?
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace ChatProgram
{
public partial class Window : Form
{
Socket sck;
EndPoint epLocal, epRemote;
public Window()
{
InitializeComponent();
sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //Starts New Socket In InternNetwork Dgram Protocoltype UDP
sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPMe.Text = GetLocalIP(); //Sets My IP Bar To My Local IP
}
private string GetLocalIP() //Gets Local IP From Computer
{
Send.Enabled = false;
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
return "127.0.0.1";
}
private void MessageCallBack(IAsyncResult aResult)
{
try
{
int size = sck.EndReceiveFrom(aResult, ref epRemote);
if (size > 0)
{
byte[] recivedData = new byte[1464];
recivedData = (byte[])aResult.AsyncState;
ASCIIEncoding eEncoding = new ASCIIEncoding();
string recivedMessage = eEncoding.GetString(recivedData);
MessageBox.Items.Add("" + recivedMessage); //Paste Messages In MessageBox listMessage.Items.Add(""+recivedMessage);
}
byte[] buffer = new byte[1500];
sck.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
}
catch (Exception exp)
{
System.Windows.Forms.MessageBox.Show(exp.ToString());
}
}
private void Connect_Click(object sender, EventArgs e)
{
try
{
epLocal = new IPEndPoint(IPAddress.Parse(IPMe.Text), Convert.ToInt32(PortMe.Text)); //MyPort And MyIP Make Port to Int32
sck.Bind(epLocal); //Socket Bind To epLocal
epRemote = new IPEndPoint(IPAddress.Parse(IpConnectingTo.Text), Convert.ToInt32(PortConnectingTo.Text)); //MyPort And MyIP Make Port to Int32
sck.Connect(epRemote); //Socket Bind To epRemote
byte[] buffer = new byte[1500];
sck.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
Connect.Text = "Connected"; //Set Text To Connected
Connect.Enabled = false; //Disabled (Gray)
Send.Enabled = true; //Enable Send Button
TextBoxSendMessages.Focus(); //Set Focus To This!
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.ToString());
}
}
private void Send_Click(object sender, EventArgs e)
{
try
{
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
byte[] msg = new byte[1500];
string nickandtext = NickNameMe.Text + ": " + TextBoxSendMessages.Text;
msg = enc.GetBytes(nickandtext); //Messages The Sum Of Both
//msg = enc.GetBytes(NickNameMe.Text + TextBoxSendMessages.Text);
sck.Send(msg); //Send Message In Bytes
MessageBox.Items.Add(NickNameMe.Text + ": " + TextBoxSendMessages.Text); //See yourself msg in msgbox
TextBoxSendMessages.Clear(); //Clear Text Message Box
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.ToString());
}
}
private void IPMe_TextChanged(object sender, EventArgs e)
{
}
private void MessageBox_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void label2_Click(object sender, EventArgs e)
{
}
}
}
Picture of program:

using System.Net.Sockets; not supported in windows store app architecture, what to use instead?

I created a simple client and server app in windows forms, now I wanted to create it in windows store app framework. using System.Net.Sockets; isnt supported there . How should I approach to this and what class should i use ? Following is the code in winforms c#: many thanks
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Media;
namespace ChatClient
{
public partial class Form1 : Form
{
Socket sck;
EndPoint epLocal, epRemote;
public Form1()
{
InitializeComponent();
//what would I use instead in windows store app, using System.Net.Sockets; namespace isnt supported ?
sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sck.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
//Getting local IP address through code
private string GetLocalIP()
{
IPHostEntry host;
string localIP = "";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
break;
}
}
return localIP;
}
private void MessageCallBack (IAsyncResult aResult)
{
try
{
int size = sck.EndReceiveFrom(aResult, ref epRemote);
if (size>0)
{
byte[] receivedData = new byte[1464];
receivedData = (byte[])aResult.AsyncState;
ASCIIEncoding eEncoding = new ASCIIEncoding();
string receiveMessage = eEncoding.GetString(receivedData);
listMessage.Items.Add("Friend : "+receiveMessage);
}
byte[] buffer = new byte[1500];
sck.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
groupBox1.Text = Environment.UserName;
textBox1.Text = GetLocalIP().ToString();
btnSend.Enabled = false;
}
private void btnStart_Click(object sender, EventArgs e)
{
try
{
if (CheckConnection() == 1)
{
btnStart.Text = "Please Wait...";
Thread.Sleep(2000);
epLocal = new IPEndPoint(IPAddress.Parse(textBox1.Text), Convert.ToInt32(comboBox1.Text));
sck.Bind(epLocal);
epRemote = new IPEndPoint(IPAddress.Parse(fndIP.Text), Convert.ToInt32(comboBox2.Text));
sck.Connect(epRemote);
byte[] buffer = new byte[1500];
sck.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
btnStart.Enabled = false;
btnStart.Text = "Connected";
btnStart.BackColor = Color.LightGreen;
btnStart.ForeColor = Color.White;
btnSend.Enabled = true;
textBox5.Focus();
button1.Enabled = true;
}
else
{
MessageBox.Show("Check Your Internet connection");
}
}
catch(Exception ex1)
{
MessageBox.Show(ex1.ToString());
}
}
private void btnSend_Click(object sender, EventArgs e)
{
try
{
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
byte[] msg = new byte[1500];
msg = enc.GetBytes(textBox5.Text);
new SoundPlayer(Properties.Resources.chat).Play();
sck.Send(msg);
listMessage.Items.Add("Me : "+textBox5.Text);
new SoundPlayer(Properties.Resources.chat).Play();
textBox5.Clear();
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private int CheckConnection ()
{
Ping myPing = new Ping();
String host = "74.125.20.147";
byte[] buffer = new byte[32];
int timeout = 1000;
PingOptions pingOptions = new PingOptions();
PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
if (reply.Status == IPStatus.Success)
{
return 1;
}
else
{
return 0;
}
}
private void button1_Click(object sender, EventArgs e)
{
sck.Close();
}
}
}
From Windows 8 development > How to > How tos (XAML) > Connecting to networks and web services Connecting with sockets:
Send and receive data with TCP or UDP sockets in your Windows Runtime app using features in the Windows.Networking.Sockets namespace.
You use UDP, so see How to connect with a datagram socket (XAML) which uses the class Windows.Networking.Sockets.DatagramSocket.
It's in the Windows.Networking.Sockets namespace
See .Net for Windows Store Apps overview article for a complete description on how to deal with these differences.

if i have already connected to the server. then how i show exception saying it is already connected

how to add in exception showing the input has to be enter, if the user click on connect without entering any input? i would like the have a message box show if the user click on the connect button without entering the name, ip and port. [SOLVED]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
namespace SocketClient
{
public partial class SocketClient : Form
{
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
public SocketClient()
{
InitializeComponent();
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = clientSocket.ReceiveBufferSize;
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
}
private void msg()
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(msg));
else
textDisplay.Text = textDisplay.Text + Environment.NewLine + " >> " + readData;
}
private void buttonConnect_Click(object sender, EventArgs e)
{
readData = "Conected to NYP Server ...";
msg();
//clientSocket.Connect("127.0.0.1", 8888);
clientSocket.Connect(textIP.Text, Convert.ToInt32(textPort.Text));
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textName.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Thread ctThread = new Thread(getMessage);
ctThread.Start();
}
private void buttonSend_Click(object sender, EventArgs e)
{
// Show msg box if no server is connected
if (serverStream == null)
{
MessageBox.Show("Please connect to a server first!");
return;
}
// Send text
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textSend.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
// Clear text
textSend.Text = "";
}
private void textDisplay_TextChanged(object sender, EventArgs e)
{
textDisplay.SelectionStart = textDisplay.Text.Length;
textDisplay.ScrollToCaret();
textDisplay.Refresh();
}
private void textSend_TextChanged(object sender, EventArgs e)
{
buttonSend.Enabled = !string.IsNullOrEmpty(textSend.Text);
}
}
}
if(string.IsNullOrEmpty(textIP.Text) || string.IsNullOrEmpty(textPort.Text) || string.IsNullOrEmpty(textName.Text))
{
MessageBox.Show("Please enter IP address, Port #, and Name");
}
else
{
//they entered stuff...so, try to connect..
}
You can use TcpClient.Connected property to check whether a connection is already established or not.
if(clientSocket.Connected){
.... show error message here
}
else{
... go ahead
}
Your form holds references to both a TcpClient and a NetworkStream instance. Both of these implement IDisposable, so that they must be disposed of explicitly. You must override the Dispose method of the form and dispose of these instances if they are not null.

SocketException was unhandled

after i am connected to the server, i click on the connect button again i get SocketException was unhandled on clientSocket.Connect("127.0.0.1", 8888); How to solve this?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
namespace SocketClient
{
public partial class SocketClient : Form
{
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
public SocketClient()
{
InitializeComponent();
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = clientSocket.ReceiveBufferSize;
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
}
private void msg()
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(msg));
else
textDisplay.Text = textDisplay.Text + Environment.NewLine + " >> " + readData;
}
private void buttonConnect_Click(object sender, EventArgs e)
{
readData = "Conected to NYP Chat Server ...";
msg();
clientSocket.Connect("127.0.0.1", 8888);
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textName.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Thread ctThread = new Thread(getMessage);
ctThread.Start();
}
private void buttonSend_Click(object sender, EventArgs e)
{
// Show msg box if no server is connected
if (serverStream == null)
{
MessageBox.Show("Please connect to a server first!");
return;
}
// Send text
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textSend.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
// Clear text
textSend.Text = "";
}
private void textDisplay_TextChanged(object sender, EventArgs e)
{
textDisplay.SelectionStart = textDisplay.Text.Length;
textDisplay.ScrollToCaret();
textDisplay.Refresh();
}
private void textSend_TextChanged(object sender, EventArgs e)
{
buttonSend.Enabled = !string.IsNullOrEmpty(textSend.Text);
}
}
}
You can't connect clientSocket more than once. What do you expect to happen when you click the button the second time?
You could check the state of the socket and if it's connected then don't attempt another connection. Or put some exception handling in.

manually input in textbox and connected to the server

Right now, when i press the connect button i will be connected to the server by the default ip address and port number. clientSocket.Connect("127.0.0.1", 8888);
I would like to create 2 textbox in the GUI , 1 for the IP address and 1 for port.
So that user can manually key in the IP add and port.
May i know how to do this. thanks.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
namespace SocketClient
{
public partial class SocketClient : Form
{
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
NetworkStream serverStream = default(NetworkStream);
string readData = null;
public SocketClient()
{
InitializeComponent();
}
private void getMessage()
{
while (true)
{
serverStream = clientSocket.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = clientSocket.ReceiveBufferSize;
serverStream.Read(inStream, 0, buffSize);
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
readData = "" + returndata;
msg();
}
}
private void msg()
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(msg));
else
textDisplay.Text = textDisplay.Text + Environment.NewLine + " >> " + readData;
}
private void buttonConnect_Click(object sender, EventArgs e)
{
readData = "Conected to NYP Chat Server ...";
msg();
//
clientSocket.Connect("127.0.0.1", 8888);
serverStream = clientSocket.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(textName.Text + "$");
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
Thread ctThread = new Thread(getMessage);
ctThread.Start();
}
private void buttonSend_Click(object sender, EventArgs e)
{
}
private void textDisplay_TextChanged(object sender, EventArgs e)
{
}
}
}
In the designer view, add two TextBoxes in the desired positions and name the texbboxes as tbIp and tbPort.
update the line following line
clientSocket.Connect("127.0.0.1", 8888);
to
clientSocket.Connect(tbIp.Text, Convert.Int32(tbPort.Text));
Regards
ArunDhaJ

Categories

Resources