using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace ChatClient
{
public partial class Form1 : Form
{
// Will hold the user name
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()
{
// On application exit, don't forget to disconnect first
Application.ApplicationExit += new EventHandler(OnApplicationExit);
InitializeComponent();
}
// The event handler for application exit
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(txtIp.Text);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
tcpServer.Connect(ipAddr, 1986);
// Helps us track whether we're connected or not
Connected = true;
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(txtUser.Text);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
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)
{
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
}
// This method is called from a different thread in order to update the log TextBox
private void UpdateLog(string strMessage)
{
// Append text also scrolls the TextBox to the bottom each time
txtLog.AppendText(strMessage + "\r\n");
}
// Closes a current connection
private void CloseConnection(string Reason)
{
// Close the objects
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
}
C# networking, threading
Found a chat client and server tutorial wich i'm trying to use as networking code for my game.
The client code crashes/breaks on exit with "Unable to read data from the transport connection:
A blocking operation was interrupted by a call to WSACancelBlockingCall" error
THe error pops inside the ReceiveMessages function in the while loop after the exit function is called
I'm not sure if the reason relies in threading or something else. When the app breaks the connected var evaluates false so I don't even understand how the program gets in the while loop
[Edited by - Calin on October 24, 2008 4:11:40 PM]
Are you following this tutorial? Why I found the code you post is not complete?
I think this line is critical as well:
I think when you click the button, a separate thread is started, and this thread will delegate to another method: UpdateLogCallback() to receive msg, i think.
I think this line is critical as well:
private void btnConnect_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."); } }
Quote:
When the app breaks the connected var evaluates false so I don't even understand how the program gets in the while loop?
I think when you click the button, a separate thread is started, and this thread will delegate to another method: UpdateLogCallback() to receive msg, i think.
private void InitializeConnection() { // Parse the IP address from the TextBox into an IPAddress object ipAddr = IPAddress.Parse(txtIp.Text); // Start a new TCP connections to the chat server tcpServer = new TcpClient(); tcpServer.Connect(ipAddr, 1986); // Helps us track whether we're connected or not Connected = true; // Prepare the form UserName = txtUser.Text; // Disable and enable the appropriate fields txtIp.Enabled = false; txtUser.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(txtUser.Text); swSender.Flush(); // Start the thread for receiving messages and further communication thrMessaging = new Thread(new ThreadStart(ReceiveMessages)); thrMessaging.Start(); }
>>Are you following this tutorial? Why I found the code you post is not complete?
Yes, I trimmed the unimportant bits.
>>I think this line is critical as well:
When you press the button while you are connected CloseConnection() is called, however that does the same thing as the other function I'm using - OnApplicationExit -
>>I think when you click the button, a separate thread is started, and this thread will delegate to another method: UpdateLogCallback() to receive msg, i think.
I don't know much about threading but to my mind the new thread should check the while condition each time it gives the while loop a spin.
[Edited by - Calin on October 25, 2008 6:20:02 AM]
Yes, I trimmed the unimportant bits.
>>I think this line is critical as well:
When you press the button while you are connected CloseConnection() is called, however that does the same thing as the other function I'm using - OnApplicationExit -
>>I think when you click the button, a separate thread is started, and this thread will delegate to another method: UpdateLogCallback() to receive msg, i think.
I don't know much about threading but to my mind the new thread should check the while condition each time it gives the while loop a spin.
[Edited by - Calin on October 25, 2008 6:20:02 AM]
I don't know much about socket prog, but based on my google-fu (i found this new hot word in gamedev) , I found this and this. Hope it helps you.
Quoted from a guy in that post:
:)
Quoted from a guy in that post:
Quote:
Well, networking is kind of fragile. It relies on a lot of intermediate components outside your control and your own code needs to anticipate the kinds of things that can occur.
:)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement