I try to connect from my pc to other pc what I have at home and both are connected to the internet. So I check the other pc with the program MyIpAdress and it is like: 38.xx.xx.xx.
And I have this program:The server:
public delegate void StatusChangedHandler(object sender, StatusChangedEventArgs e);
public class StatusChangedEventArgs : EventArgs
{
// This will store our only parameter / event argument, which is the event message
private string EventMsg;
// We need to define this property in order to retrieve the message in the event handler, back in Form1.cs
public string EventMessage
{
get
{
return EventMsg;
}
}
// The constructor will set the message
public StatusChangedEventArgs(string strEventMsg)
{
EventMsg = strEventMsg;
}
}
class Monitor
{
// Will store the IP address passed to it
IPAddress ipAddress;
// The constructor sets the IP address to the one retrieved by the instantiating object
public Monitor(IPAddress address)
{
ipAddress = address;
}
// Declare the event that we'll fire later
public event StatusChangedHandler StatusChangedEvent;
// The thread that will hold the connection listener
private Thread thrListener;
// The TCP object that listens for connections
private TcpListener tlsServer;
// The thread that will send information to the client
private Thread thrSender;
// Will tell the while loop to keep monitoring for connections
bool ServRunning = false;
public void StartMonitoring()
{
// Get the IP of the first network device, however this can prove unreliable on certain configurations
IPAddress ipaLocal = ipAddress;
if (tlsServer == null)
{
// Create the TCP listener object using the IP of the server and the specified port
tlsServer = new TcpListener(ipaLocal, 1986 );
}
// Start the TCP listener and listen for connections
tlsServer.Start();
// The while loop will check for true in this before checking for connections
ServRunning = true;
// Start the new tread that hosts the listener
thrListener = new Thread(KeepListening);
thrListener.Start();
}
private void KeepListening()
{
TcpClient tclServer;
// While the server is running
while (ServRunning == true)
{
// Accept a pending connection
tclServer = tlsServer.AcceptTcpClient();
// Start a new thread where our new client who just connected will be managed
thrSender = new Thread(new ParameterizedThreadStart(AcceptClient));
// The thread calls the AcceptClient() method
thrSender.Start(tclServer);
}
}
// Occures when a new client is accepted
private void AcceptClient(object newClient)
{
// Set the argument/parameter to a message explaining what just happened
StatusChangedEventArgs evArg = new StatusChangedEventArgs("A client was successfully accepted.");
// Fire the event because a new client was accepted
StatusChangedEvent(this, evArg);
}
}
But if I fill in in the textbox the ipadress: 38.xxx.xxx.xx,
I will get this error:
An unhandled exception of type 'System.Net.Sockets.SocketException'
occurred in System.dll
Additional information: The requested address is not valid in its context
So it can only see Local ipAdresses?
But how to change it, that it also finds not local Ipadresses?
And this is the client application:
public partial class Form1 : Form
{
private string UserName = "Unknown";
private StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
// Needed to update the form with messages from another thread
private delegate void UpdateLogCallback(string strMessage);
// Needed to set the form to a "disconnected" state from another thread
private delegate void CloseConnectionCallback(string strReason);
private Thread thrMessaging;
private IPAddress ipAddr;
private bool Connected;
public Form1()
{
Application.ApplicationExit += new EventHandler(OnApplicationExit);
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// If we are not currently connected but awaiting to connect
if (Connected == false)
{
// Initialize the connection
InitializeConnection();
}
else // We are connected, thus disconnect
{
CloseConnection("Disconnected at user's request.");
}
}
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Connected Successfully!" });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = "Not Connected: ";
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length - 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
}
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(txtServerIP.Text);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
tcpServer.Connect(IPAddress.Any, 1986);
// Helps us track whether we're connected or not
Connected = true;
// Prepare the form
UserName = txtUserName.Text;
// Disable and enable the appropriate fields
txtServerIP.Enabled = false;
txtUserName.Enabled = false;
txtMessage.Enabled = true;
btnSend.Enabled = true;
btnConnect.Text = "Disconnect";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(txtUserName.Text);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void UpdateLog(string strMessage)
{
// Append text also scrolls the TextBox to the bottom each time
txtLog.AppendText(strMessage + "\r\n");
}
private void btnSend_Click(object sender, EventArgs e)
{
SendMessage();
}
private void SendMessage()
{
if (txtMessage.Lines.Length >= 1)
{
swSender.WriteLine(txtMessage.Text);
swSender.Flush();
txtMessage.Lines = null;
}
txtMessage.Text = "";
}
// Closes a current connection
private void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
txtLog.AppendText(Reason + "\r\n");
// Enable and disable the appropriate controls on the form
txtServerIP.Enabled = true;
txtUserName.Enabled = true;
txtMessage.Enabled = false;
btnSend.Enabled = false;
btnConnect.Text = "Connect";
// Close the objects
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
}
So I changed this line:
tcpServer.Connect(IPAddress.Any, 1986);
but If I run the server application I will get this error:
I get the same error as by the client:
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Additional information: The requested address is not valid in its context
Thank you
I show you two Images:This is the Server app. That works
This is the Client app, that doesnt work:
And if I change the code in the client app, like this:
tcpServer.Connect(ipAddr, 1986); Then I will get this error:
Additional information: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
But I can pin the other pc
In the client program I have this:
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(txtServerIP.Text);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
tcpServer.Connect(IPAddress.Any, 1986);
// Helps us track whether we're connected or not
Connected = true;
// Prepare the form
UserName = txtUserName.Text;
// Disable and enable the appropriate fields
txtServerIP.Enabled = false;
txtUserName.Enabled = false;
txtMessage.Enabled = true;
btnSend.Enabled = true;
btnConnect.Text = "Disconnect";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(txtUserName.Text);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
what I have to change then?
Maybe you have to allow TCP connections on your port in the firewall for the applications on both PCs. Make sure that connections from and to the network are allowed.
Related
I'm creating a game in which I use TCP/IP connection. The problem is that I'm using .Invoke to help me receive and send message.
The program goes like this: I'm my first window, i'm starting and connecting to the server like this :
{
TcpListener listener = new TcpListener(IPAddress.Any, this.port);
listener.Start();
try {
this.client = listener.AcceptTcpClient();
gameWindow = new GameWindow(this.client, true);
gameWindow.StartGame();
}
}
then i'm connecting to it like this:
{
IPEndPoint ipEnd = new IPEndPoint(this.serverIP, this.port);
{
try {
client.Connect(ipEnd);
if (client.Connected) {
gameWindow = new GameWindow(this.client, false);
gameWindow.StartGame();
}
}
}
The constructor for gameWindow (which is a form) looks like this:
public GameWindow(TcpClient thisClient, bool isServer)
{
InitializeComponent();
this.client = thisClient;
this.reader = new StreamReader(thisClient.GetStream());
this.writer = new StreamWriter(thisClient.GetStream());
this.writer.AutoFlush = true;
}
I must wait for the server to send a message to the client, and then start the client ( I have a function .startGame() that uses .ShowDialog() and creates some pictureBoxs)
But nowhere I can get my handle created. I've tried to put this.createHandle() (read about it here) into GameWindow_Load but still not works. If I try to send a message with:
workerSendData.RunWorkerAsync(); I get:
Additional information: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
What can I do to get my handler created? Using Thread.Sleep will sleep my whole UI, which does not work (a "solution" found on the internet)
My code for sending message :
private void workerSendData_DoWork(object sender, DoWorkEventArgs e)
{
if (client.Connected) {
this.writer.WriteLine(this.toSend); // aici trimitem datele.
// de modificat : aici vom adauga in lista noastra miscarile.
this.Invoke(new MethodInvoker(delegate () { MessageBox.Show("Me:" + this.toSend + "\n"); }));
}
else {
MessageBox.Show("Send failed");
}
workerSendData.CancelAsync();
}
My code for receiving data:
private void workerReceiveData_DoWork(object sender, DoWorkEventArgs e)
{
while (client.Connected) {
try {
this.received = this.reader.ReadLine();
this.myTurn = true;
this.Invoke(new MethodInvoker(delegate () {
MessageBox.Show("This has been received: " + this.received);
/*this.tbReceive.AppendText("You:" + this.received + "\n");*/
}));
this.received = "";
}
catch (Exception x) {
MessageBox.Show(x.Message.ToString());
}
}
}
It seems that you cannot invoke an action before the Window is fully initialized and loaded. Assuming you are working in Windows Forms, there is a solution provided by #Greg D on this question, but it doesn't be to be the safest way to go.
I would suggest that you try to find a way to start the worker only after the window is loaded (for example using the Loaded event), so that the handle is definitely ready and this situation does not occur.
I have managed to create a Server/Client chat system, where the client sends a message to the server and the the server sends the message to all the clients.
I want to extend this so that the Server compares the messages and then sends a message to the client.
For Example: If client 1 sends 10 and client 2 sends 20 the server will compare these and the server will send a message saying 20 is more than 10.
Is this possible to do? And if so how?
Server Code:
namespace Server
{
public partial class Form1 : Form
{
private const int m_iMaxConnections = 2;
struct Connection_Struct // Define a structure to hold details about a single connection
{
public Socket ClientSpecific_Socket;
public bool bInUse;
};
Socket m_ListenSocket;
Socket m_SendSocket;
Connection_Struct[] m_Connection_Array = new Connection_Struct[m_iMaxConnections]; // Define an array to hold a number of connections
System.Net.IPEndPoint m_LocalIPEndPoint;
static int m_iNumberOfConnectedClients;
private static System.Windows.Forms.Timer m_CommunicationActivity_Timer;
public Form1()
{
InitializeComponent();
Initialise_ConnectionArray();
m_CommunicationActivity_Timer = new System.Windows.Forms.Timer(); // Check for communication activity on Non-Blocking sockets every 200ms
m_CommunicationActivity_Timer.Tick += new EventHandler(OnTimedEvent_PeriodicCommunicationActivityCheck); // Set event handler method for timer
m_CommunicationActivity_Timer.Interval = 100; // Timer interval is 1/10 second
m_CommunicationActivity_Timer.Enabled = false;
string szLocalIPAddress = GetLocalIPAddress_AsString(); // Get local IP address as a default value
txtIPAddress.Text = szLocalIPAddress; // Place local IP address in IP address field
txtPort.Text = "8000"; // Default port number
m_iNumberOfConnectedClients = 0;
txtClientNo.Text = System.Convert.ToString(m_iNumberOfConnectedClients);
try
{ // Create the Listen socket, for TCP use
m_ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_ListenSocket.Blocking = false;
m_SendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Tcp);
}
catch (SocketException se)
{ // If an exception occurs, display an error message
MessageBox.Show(se.Message);
}
}
private void Initialise_ConnectionArray()
{
int iIndex;
for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
{
m_Connection_Array[iIndex].bInUse = false;
}
}
private void btnEnableServer_Click(object sender, EventArgs e)
{
// Bind to the selected port and start listening / receiving
try
{
// Get the Port number from the appropriate text box
String szPort = txtPort.Text;
int iPort = System.Convert.ToInt16(szPort, 10);
// Create an Endpoint that will cause the listening activity to apply to all the local node's interfaces
m_LocalIPEndPoint = new System.Net.IPEndPoint(IPAddress.Any, iPort);
// Bind to the local IP Address and selected port
m_ListenSocket.Bind(m_LocalIPEndPoint);
txtLog.Text = "Bind succeded";
// Prevent any further changes to the port number
txtPort.ReadOnly = true;
}
catch // Catch any errors
{ // If an exception occurs, display an error message
txtLog.Text = "Bind failed";
}
try
{
txtLog.Text = "Listening";
m_ListenSocket.Listen(2); // Listen for connections, with a backlog / queue maximum of 2
}
catch (SocketException se)
{
// If an exception occurs, display an error message
MessageBox.Show(se.Message);
}
catch // Silently handle any other exception
{
}
m_CommunicationActivity_Timer.Start(); // Start the timer to perform periodic checking for connection requests
txtLog.Text = "Accepting (waiting for connection attempt)";
btnEnableServer.Enabled = false;
}
private void OnTimedEvent_PeriodicCommunicationActivityCheck(Object myObject, EventArgs myEventArgs)
{ // Periodic check whether a connection request is pending or a message has been received on a connected socket
// First, check for pending connection requests
int iIndex;
iIndex = GetnextAvailable_ConnectionArray_Entry(); // Find an available array entry for next connection request
if (-1 != iIndex)
{ // Only continue with Accept if there is an array entry available to hold the details
try
{
m_Connection_Array[iIndex].ClientSpecific_Socket = m_ListenSocket.Accept(); // Accept a connection (if pending) and assign a new socket to it (AcceptSocket)
// Will 'catch' if NO connection was pending, so statements below only occur when a connection WAS pending
m_Connection_Array[iIndex].bInUse = true;
m_Connection_Array[iIndex].ClientSpecific_Socket.Blocking = false; // Make the new socket operate in non-blocking mode
m_iNumberOfConnectedClients++;
txtClientNo.Text = System.Convert.ToString(m_iNumberOfConnectedClients);
txtLog.Text = "A new client connected";
SendUpdateMesageToAllConnectedclients();
}
catch (SocketException se) // Handle socket-related exception
{ // If an exception occurs, display an error message
if (10053 == se.ErrorCode || 10054 == se.ErrorCode) // Remote end closed the connection
{
CloseConnection(iIndex);
}
else if (10035 != se.ErrorCode)
{ // Ignore error messages relating to normal behaviour of non-blocking sockets
MessageBox.Show(se.Message);
}
}
catch // Silently handle any other exception
{
}
}
// Second, check for received messages on each connected socket
for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
{
if (true == m_Connection_Array[iIndex].bInUse)
{
try
{
EndPoint localEndPoint = (EndPoint)m_LocalIPEndPoint;
byte[] ReceiveBuffer = new byte[1024];
int iReceiveByteCount;
iReceiveByteCount = m_Connection_Array[iIndex].ClientSpecific_Socket.ReceiveFrom(ReceiveBuffer, ref localEndPoint);
string szReceivedMessage;
if (0 < iReceiveByteCount)
{ // Copy the number of bytes received, from the message buffer to the text control
szReceivedMessage = Encoding.ASCII.GetString(ReceiveBuffer, 0, iReceiveByteCount);
if ("QuitConnection" == szReceivedMessage)
{
CloseConnection(iIndex);
}
else
{
txtLog.AppendText(szReceivedMessage + Environment.NewLine);
// Send message to each connected client.
// int iIndex2;
for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
{
if (true == m_Connection_Array[iIndex].bInUse)
{
string szMessage;
szMessage = szReceivedMessage;
txtLog.Text = m_Connection_Array[m_iMaxConnections].ToString();
byte[] SendMessage = System.Text.Encoding.ASCII.GetBytes(szMessage);
m_Connection_Array[iIndex].ClientSpecific_Socket.Send(SendMessage, SocketFlags.None);
}
}
}
}
}
catch (SocketException se) // Handle socket-related exception
{ // If an exception occurs, display an error message
if (10053 == se.ErrorCode || 10054 == se.ErrorCode) // Remote end closed the connection
{
CloseConnection(iIndex);
}
else if (10035 != se.ErrorCode)
{ // Ignore error messages relating to normal behaviour of non-blocking sockets
MessageBox.Show(se.Message);
}
}
catch // Silently handle any other exception
{
}
}
}
}
private void SendUpdateMesageToAllConnectedclients()
{ // Send message to each connected client informing of the total number of connected clients
int iIndex;
for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
{
if (true == m_Connection_Array[iIndex].bInUse)
{
string szMessage;
if (1 == m_iNumberOfConnectedClients)
{
szMessage = string.Format("There is now {0} client connected", m_iNumberOfConnectedClients);
}
else
{
szMessage = string.Format("There are now {0} clients connected", m_iNumberOfConnectedClients);
}
byte[] SendMessage = System.Text.Encoding.ASCII.GetBytes(szMessage);
m_Connection_Array[iIndex].ClientSpecific_Socket.Send(SendMessage, SocketFlags.None);
}
}
}
private void CloseConnection(int iIndex)
{
try
{
m_Connection_Array[iIndex].bInUse = false;
m_Connection_Array[iIndex].ClientSpecific_Socket.Shutdown(SocketShutdown.Both);
m_Connection_Array[iIndex].ClientSpecific_Socket.Close();
m_iNumberOfConnectedClients--;
txtClientNo.Text = System.Convert.ToString(m_iNumberOfConnectedClients);
txtLog.Text = "A Connection was closed";
SendUpdateMesageToAllConnectedclients();
}
catch // Silently handle any exceptions
{
}
}
private void Close_And_Quit()
{ // Close the sockets and exit the application
try
{
m_ListenSocket.Close();
}
catch
{
}
try
{
int iIndex;
for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
{
m_Connection_Array[iIndex].ClientSpecific_Socket.Shutdown(SocketShutdown.Both);
m_Connection_Array[iIndex].ClientSpecific_Socket.Close();
}
}
catch
{
}
try
{
Close();
}
catch
{
}
}
public string GetLocalIPAddress_AsString()
{
string szHost = Dns.GetHostName();
string szLocalIPaddress = "127.0.0.1"; // Default is local loopback address
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress IP in IPHost.AddressList)
{
if (IP.AddressFamily == AddressFamily.InterNetwork) // Match only the IPv4 address
{
szLocalIPaddress = IP.ToString();
break;
}
}
return szLocalIPaddress;
}
private int GetnextAvailable_ConnectionArray_Entry()
{
int iIndex;
for (iIndex = 0; iIndex < m_iMaxConnections; iIndex++)
{
if (false == m_Connection_Array[iIndex].bInUse)
{
return iIndex; // Return the index value of the first not-in-use entry found
}
}
return -1; // Signal that there were no available entries
}
}
}
Client Code:
namespace Client
{
public partial class Form1 : Form
{
Socket m_ClientSocket;
System.Net.IPEndPoint m_remoteEndPoint;
IPEndPoint m_localIPEndPoint;
Socket m_ReceiveSocket;
private static System.Windows.Forms.Timer m_CommunicationActivity_Timer;
public Form1()
{
InitializeComponent();
m_CommunicationActivity_Timer = new System.Windows.Forms.Timer(); // Check for communication activity on Non-Blocking sockets every 200ms
m_CommunicationActivity_Timer.Tick += new EventHandler(OnTimedEvent_PeriodicCommunicationActivityCheck); // Set event handler method for timer
m_CommunicationActivity_Timer.Interval = 100; // Timer interval is 1/10 second
m_CommunicationActivity_Timer.Enabled = false;
string szLocalIPAddress = GetLocalIPAddress_AsString(); // Get local IP address as a default value
txtIPAddress.Text = szLocalIPAddress; // Place local IP address in IP address field
txtPort.Text = "8000"; // Default port number
}
private void btnConnect_Click(object sender, EventArgs e)
{
// Connect the Socket with a remote endpoint
try
{
// Create the socket, for TCP use
m_ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_ClientSocket.Blocking = true; // Socket operates in Blocking mode initially
}
catch // Handle any exceptions
{
Close_Socket_and_Exit();
}
try
{
// Get the IP address from the appropriate text box
String szIPAddress = txtIPAddress.Text;
System.Net.IPAddress DestinationIPAddress = System.Net.IPAddress.Parse(szIPAddress);
// Get the Port number from the appropriate text box
String szPort = txtPort.Text;
int iPort = System.Convert.ToInt16(szPort, 10);
// Combine Address and Port to create an Endpoint
m_remoteEndPoint = new System.Net.IPEndPoint(DestinationIPAddress, iPort);
m_ClientSocket.Connect(m_remoteEndPoint);
m_ClientSocket.Blocking = false; // Socket is now switched to Non-Blocking mode for send/ receive activities
txtLog.Text = "Connected";
m_CommunicationActivity_Timer.Start(); // Start the timer to perform periodic checking for received messages
}
catch // Catch all exceptions
{ // If an exception occurs, display an error message
txtLog.Text = "(Connect attempt failed)\nRetry Connect";
}
}
private void OnTimedEvent_PeriodicCommunicationActivityCheck(Object myObject, EventArgs myEventArgs)
{ // Periodic check whether a message has been received
try
{
EndPoint RemoteEndPoint = (EndPoint)m_remoteEndPoint;
byte[] ReceiveBuffer = new byte[1024];
int iReceiveByteCount;
iReceiveByteCount = m_ClientSocket.ReceiveFrom(ReceiveBuffer, ref RemoteEndPoint);
string szReceivedMessage;
if (0 < iReceiveByteCount)
{ // Copy the number of bytes received, from the message buffer to the text control
szReceivedMessage = Encoding.ASCII.GetString(ReceiveBuffer, 0, iReceiveByteCount);
txtResult.Text = szReceivedMessage;
}
}
catch // Silently handle any exceptions
{
}
}
private void Close_Socket_and_Exit()
{
try
{
m_ClientSocket.Shutdown(SocketShutdown.Both);
}
catch // Silently handle any exceptions
{
}
try
{
m_ClientSocket.Close();
}
catch // Silently handle any exceptions
{
}
this.Close();
}
private void btnDisconnect_Click(object sender, EventArgs e)
{
try
{
String szData = "QuitConnection"; // Special code to signal 'close connection' to the server
// This ensures that the server is aware the Client wants to close the connection
// (TCP should otherwise automatically detect disconnection, but this approach ensures a clean disconnect)
byte[] byData = System.Text.Encoding.ASCII.GetBytes(szData);
m_ClientSocket.Send(byData, SocketFlags.None);
m_ClientSocket.Shutdown(SocketShutdown.Both);
m_ClientSocket.Close();
btnConnect.Text = "Connect";
txtResult.Text = "";
}
catch // Silently handle any exceptions
{
}
}
private string GetLocalIPAddress_AsString()
{
string szHost = Dns.GetHostName();
string szLocalIPaddress = "127.0.0.1"; // Default is local loopback address
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress IP in IPHost.AddressList)
{
if (IP.AddressFamily == AddressFamily.InterNetwork) // Match only the IPv4 address
{
szLocalIPaddress = IP.ToString();
break;
}
} return szLocalIPaddress;
}
}
}
I building a client/server chat app , where the server is listening on IP number 127.0.0.1 and port 1212 , and clients are supposed to connect to that IP & Port .
The problem - in the following order :
I run the server on my computer , listening on (127.0.0.1 & port 1212)
I'm also running a client on my computer (the same computer as #1) that successfully connects to the server (127.0.0.1 & port 1212)
I'm running another client from a different IP , but when trying connect to the server (127.0.0.1 & port 1212) the attempt failed . In this IP , I do not run another server !!!
I don't understand the reason for that ... here is the code :
Server side :
public partial class ServerForm : Form
{
private TcpListener m_tcpServer;
private TcpClient m_tcpClient;
private Thread th;
private ServerNotifier m_chatDialog;
private List<ServerNotifier> m_formArray = new List<ServerNotifier>();
private ArrayList m_threadArray = new ArrayList();
public delegate void ChangedEventHandler(object sender, EventArgs e);
public event ChangedEventHandler m_Changed;
public delegate void SetListBoxItem(String str, String type);
// some code
public void StartListen()
{
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
m_tcpServer = new TcpListener(localAddr, Int32.Parse(tbPortNumber.Text));
m_tcpServer.Start();
// Keep on accepting Client Connection
while (true)
{
// New Client connected, call Event to handle it.
Thread t = new Thread(new ParameterizedThreadStart(NewClient));
m_tcpClient = m_tcpServer.AcceptTcpClient();
t.Start(m_tcpClient);
}
}
}
The winform of the server ....
Client side :
public partial class ClientForm : Form
{
// to know when a button was clicked
private bool m_connectionEstablished = false;
private bool m_enterKeyPressed = false;
private bool m_notRunning = false; // flip this when the server is not running
private NetworkStream m_ns = null;
private StateObject m_state = null;
private TcpClient m_clientTcpConnection = null;
// ip and m_username entered by the client
private String m_ipNumberString = String.Empty;
private String m_username = String.Empty;
private int m_port = 0;
public bool StartTheClient(int m_port)
{
byte[] data = new byte[1024];
string inputFromClient = "";
string portString = "";
try
{
// "127.0.0.1"
this.m_clientTcpConnection = new TcpClient(this.m_ipNumberString , this.m_port);
}
catch (Exception e)
{
// this.rtbClientChat.SelectionColor = Color.LimeGreen;
this.m_notRunning = true; // m_clientTcpConnection is not running
MessageBox.Show("The server is currently not running , try again later!");
// connection failed
return false;
}
this.rtbClientChat.SelectedText = "Connected to the Server...";
String local_IP = ((IPEndPoint)m_clientTcpConnection.Client.LocalEndPoint).Address.ToString();
String local_Port = ((IPEndPoint)m_clientTcpConnection.Client.LocalEndPoint).Port.ToString();
this.rtbClientChat.SelectedText = "\nConnected on IP address " + local_IP + " and Port " + local_Port;
this.rtbClientChat.SelectedText = "\nEnter a message to send to the Server";
this.m_ns = m_clientTcpConnection.GetStream();
this.m_state = new StateObject();
this.m_state.workSocket = m_clientTcpConnection.Client;
this.m_clientTcpConnection.Client.BeginReceive(m_state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(OnReceive), m_state);
// connection established successfully
this.m_connectionEstablished = true;
return true;
}
/// <summary>
/// connet/disconnect
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (this.connectionLabel.Checked == true)
{
// then the user checked the "connet/disconnect" checkbox
// now check if the user also filled the m_port number
try
{
// trying to check if the user entered something is the m_port box
// grab port number
m_port = Int32.Parse(this.boxPortNumber.Text);
m_ipNumberString = this.ipBoxNumber.Text;
// grab IP number
if (m_ipNumberString == string.Empty)
{
MessageBox.Show("Please enter a valid IP Number!");
this.connectionLabel.Checked = false;
return;
}
// grab username
this.m_username = this.usernameBox.Text;
if (this.m_username == string.Empty)
{
MessageBox.Show("Please enter a Username!");
this.connectionLabel.Checked = false;
return;
}
StartTheClient(m_port);
}
catch (Exception exp)
{
if (this.m_notRunning == true)
{
// then the user tried to initiate connection
// while the m_clientTcpConnection is disconnected
this.m_notRunning = false;
}
else
{
// the user didn't put anything in the m_port box
MessageBox.Show("Please enter a Port number !");
this.connectionLabel.Checked = false;
}
}
}
}
Its winform :
Any idea why this is happening ?
Much appreciated !
127.0.0.1 is a localhost. You should specify the IP of the server in the network. You can easily find the IP of the server by running ipconfig in command prompt.
And the listener should also be started on that IP address.
127.0.0.1 In computer networking, localhost means this computer. So if you run your client on another pc, it will try to connect to the server on that pc, but your server is on another. Set the client IP to the one where you have the server.
127.0.0.1
In case if you have more than one network interface on the server you should start your listener like this, for more details follow the link:
m_tcpServer = new TcpListener(IPAddress.Any, Int32.Parse(tbPortNumber.Text));
TcpListener Constructor
Every device has its own localhost (127.0.0.1).
You cannot connect to another PC localhost (127.0.0.1), so your server should have IP such as 192.168.0.1 with specified port which is reachable from another PC.
If not, everytime it will only try to connect to its own localhost!
normally we just use localhost to test our network program internally. but it won't success if you want test externally with localhost.
127.0.0.1 on any machine refers to itself ( localhost) .
So your client code on different machine need to refer to a server IP.
Every machine has two IP's one is internal 127.0.0.1 and other can be external like 192.168.1.10
You need to provide the client code with a external IP address in that LAN
I have a test web connection form in c#. I want to show a loading window while my connection is being checked, and then show the result of checking.
This is my code for testing the web connection:
public bool ConnectionAvailable(string strServer)
{
try
{
HttpWebRequest reqFP = (HttpWebRequest)HttpWebRequest.Create(strServer);
HttpWebResponse rspFP = (HttpWebResponse)reqFP.GetResponse();
if (HttpStatusCode.OK == rspFP.StatusCode)
{
// HTTP = 200 - Internet connection available, server online
rspFP.Close();
return true;
}
else
{
// Other status - Server or connection not available
rspFP.Close();
return false;
}
}
catch (WebException)
{
// Exception - connection not available
return false;
}
}
And this:
private void button1_Click(object sender, EventArgs e)
{
string url = "Web-url";
label1.Text = "Checking ...";
button1.Enabled = false;
if (ConnectionAvailable(url))
{
WebClient w = new WebClient();
w.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
label1.Text = w.UploadString(url, "post", "SN=" + textBox1.Text);
button1.Enabled = true;
}
else
{
label1.Text = "Conntion fail";
button1.Enabled = true;
}
}
On a windows forms application the user interface runs on one thread, if you try to run a long running process, which checking the web connection might end up being this will cause the form to freeze until it completes the work.
So, I'd start a new thread that does the check. then raise an event to return the result. while all that's happening you can do what you like with the user interface, such as a loading graphic, or even allow the user to continue using features that don't require the internet connection.
Create EventArgs class of your own so you can pass back the result:
public class ConnectionResultEventArgs : EventArgs
{
public bool Available { get; set; }
}
Then in your form class, create your event, handlers and the method to action when the event arrives
//Create Event and Handler
public delegate void ConnectionResultEventHandler(object sender, ConnectionResultEventArgs e);
public event ConnectionResultEventHandler ConnectionResultEvent;
//Method to run when the event has been receieved, include a delegate in case you try to interact with the UI thread
delegate void ConnectionResultDelegate(object sender, ConnectionResultEventArgs e);
void ConnectionResultReceived(object sender, ConnectionResultEventArgs e)
{
//Check if the request has come from a seperate thread, if so this will raise an exception unless you invoke.
if (InvokeRequired)
{
BeginInvoke(new ConnectionResultDelegate(ConnectionResultReceived), new object[] { this, e });
return;
}
//Do Stuff
if (e.Available)
{
label1.Text = "Connection Good!";
return;
}
label1.Text = "Connection Bad";
}
Subscribe to the event when your form loads:
private void Form1_Load(object sender, EventArgs e)
{
//Subscribe to the the results event.
ConnectionResultEvent += ConnectionResultReceived;
}
and then setup the worker thread:
//Check the connection
void BeginCheck()
{
try
{
HttpWebRequest reqFP = (HttpWebRequest)HttpWebRequest.Create("http://google.co.uk");
HttpWebResponse rspFP = (HttpWebResponse)reqFP.GetResponse();
if (HttpStatusCode.OK == rspFP.StatusCode)
{
// HTTP = 200 - Internet connection available, server online
rspFP.Close();
ConnectionResultEvent(this, new ConnectionResultEventArgs {Available = true});
}
else
{
// Other status - Server or connection not available
rspFP.Close();
ConnectionResultEvent(this, new ConnectionResultEventArgs { Available = false });
}
}
catch (WebException)
{
// Exception - connection not available
//Raise the Event - Connection False
ConnectionResultEvent(this, new ConnectionResultEventArgs { Available = false });
}
}
private void button1_Click(object sender, EventArgs e)
{
//loading graphic, screen or whatever
label1.Text = "Checking Connection...";
//Begin the checks - Start this in a new thread
Thread t = new Thread(BeginCheck);
t.Start();
}
I am thinking of threading! One thread checks the connection while the other one is showing the loading window. If for example the connection has been established you can notify the other thread and show the result.
When a client disconnects, the server closes. Tell me how to leave the ability to connect new customers after the close of the first session .Thanks in advance.
namespace tcpserver
{
class Program
{
static void Main(string[] args)
{
string cmd;
int port = 56568;
Server Serv = new Server(); // Создаем новый экземпляр класса
// сервера
Serv.Create(port);
while (true)
{
cmd = Console.ReadLine(); // Ждем фразы EXIT когда
// понадобится выйти из приложения.
// типа интерактивность.
if (cmd == "EXIT")
{
Serv.Close(); // раз выход – значит выход. Серв-нах.
return;
}
}
//while (Serv.Close() == true) { Serv.Create(port); }
}
public class Server // класс сервера.
{
private int LocalPort;
private Thread ServThread; // экземпляр потока
TcpListener Listener; // листенер))))
public void Create(int port)
{
LocalPort = port;
ServThread = new Thread(new ThreadStart(ServStart));
ServThread.Start(); // запустили поток. Стартовая функция –
// ServStart, как видно выше
}
public void Close() // Закрыть серв?
{
Listener.Stop();
ServThread.Abort();
return;
}
private void ServStart()
{
Socket ClientSock; // сокет для обмена данными.
string data;
byte[] cldata = new byte[1024]; // буфер данных
Listener = new TcpListener(LocalPort);
Listener.Start(); // начали слушать
Console.WriteLine("Waiting connections on " + Convert.ToString(LocalPort) + " port");
try
{
ClientSock = Listener.AcceptSocket(); // пробуем принять клиента
}
catch
{
ServThread.Abort(); // нет – жаль(
return;
}
int i = 0;
if (ClientSock.Connected)
{
while (true)
{
try
{
i = ClientSock.Receive(cldata); // попытка чтения
// данных
}
catch
{
}
try
{
if (i > 0)
{
data = Encoding.ASCII.GetString(cldata).Trim();
Console.WriteLine("<" + data);
if (data == "CLOSE") // если CLOSE –
// вырубимся
{
ClientSock.Send(Encoding.ASCII.GetBytes("Closing the server..."));
ClientSock.Close();
Listener.Stop();
Console.WriteLine("Server closed. Reason: client wish! Type EXIT to quit the application.");
ServThread.Abort();
return;
}
else
{ // нет – шлем данные взад.
ClientSock.Send(Encoding.ASCII.GetBytes("Your data: " + data));
}
}
}
catch
{
ClientSock.Close(); //
Listener.Stop();
Console.WriteLine("Client disconnected. Server closed.");
ServThread.Abort();
}
}
}
}
}
}
}
Typical threaded server code will read more like this (in a pseudo code, because I don't know enough Java details to write it exactly, and because C is a bit stifling):
socket s = new socket
bind s to an optional IP, port
listen s
while true
cli = accept s
t = new thread(handle_client, cli)
maybe disown thread, so no need to join it later
t.start
The important point is that creating the socket, binding it to an address, and listen are all handled outside the loop, and accept() and starting threads are inside the loop.
You may want to wrap this entire block inside another thread; that is acceptable. The important part is separating the listen from the accept and per-client thread. This allows your code to stop accepting new connections but handle existing clients until they disconnect, or disconnect existing connections when they use their allotment of resources but continue accepting connections, etc. (Note how your last catch block will terminate the server if any single client socket throws an exception; that kind of code is easy to avoid with the usual server layout.)
replace
ServThread.Abort();
return;
with a continue instead, this will not break the while loop and yet stop the current "round". Please consider reading this: http://www.codeproject.com/KB/IP/serversocket.aspx nice project to build from