Уменя есть 2 части – 2 приложения. Это простой чат. Программирую в VS 2008.
Пример взял из книжки.
Почему не работает не понимаю
Серверная часть
public class Server : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox inputTextBox;
private System.Windows.Forms.TextBox displayTextBox;
private Socket connection;
private Thread readThread;
private System.ComponentModel.Container component = null;
private NetworkStream socketStream;
private BinaryWriter writer;
private BinaryReader reader;
public Server()
{
InitializeComponent();
readThread = new Thread(new ThreadStart(RunServer));
readThread.Start();
}
[STAThread]
static void Main()
{
Application.Run(new Server());
}
protected void Server_Closing(object sender, CancelEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
protected void inputTextBox_KeyDown(object sender, KeyEventArgs e)
{
// отправка текста клиенту
try
{
if (e.KeyCode == Keys.Enter && connection != null)
{
writer.Write("SERVER» > " + inputTextBox.Text);
displayTextBox.Text += "\r\nSERVER»> " + inputTextBox.Text;
if (inputTextBox.Text == "TERMINATE") connection.Close();
inputTextBox.Clear();
}
}
catch (SocketException)
{
displayTextBox.Text += "\nError writing object";
}
}
public void RunServer()
{
TcpListener listener;
int counter = 1;
try
{
listener = new TcpListener(5000);
listener.Start();
while (true)
{
displayTextBox.Text = "Waiting for connection\r\n";
connection = listener.AcceptSocket();
socketStream = new NetworkStream(connection);
writer = new BinaryWriter(socketStream); reader = new BinaryReader(socketStream);
displayTextBox.Text += "Connection " + counter + "received.\r\n";
writer.Write("SERVER»>,Connection successful");
inputTextBox.ReadOnly = false; string theReply = "";
do
{
try
{
theReply = reader.ReadString();
displayTextBox.Text += "\r\n" + theReply;
}
catch (Exception)
{
break;
}
} while (theReply != "CLIENT»> TERMINATE" && connection.Connected);
displayTextBox.Text += "\r\nUser terminated connection";
inputTextBox.ReadOnly = true;
writer.Close();
reader.Close();
socketStream.Close();
connection.Close();
++counter;
}
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
}
private void InitializeComponent()
{
this.SuspendLayout();
this.ClientSize = new System.Drawing.Size(292, 260);
this.Name = "Server";
this.Text = "Сервер";
this.ResumeLayout(false);
}
}
28 мая 2009 в 11:02
Ого спасибо тебе огромное!
28 мая 2009 в 0:04
Клиентская часть:
using System;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.IO;
public partial class frmClientChatForm : Form
{
public frmClientChatForm()
{
InitializeComponent();
}
private NetworkStream output;
private BinaryWriter writer;
private BinaryReader reader;
private Thread readThread;
private string message = "";
private void frmClientChatForm_Load( object sender, EventArgs e )
{
readThread = new Thread( new ThreadStart( RunClient ) );
readThread.Start();
}
private void frmClientChatForm_FormClosing( object sender,
FormClosingEventArgs e )
{
System.Environment.Exit( System.Environment.ExitCode );
}
private delegate void DisplayDelegate( string message );
private void DisplayMessage( string message )
{
if ( displayTextBox.InvokeRequired )
{
Invoke( new DisplayDelegate( DisplayMessage ),
new object[] { message } );
}
else
displayTextBox.Text += message;
}
private delegate void DisableInputDelegate( bool value );
private void DisableInput( bool value )
{
if ( inputTextBox.InvokeRequired )
{
Invoke( new DisableInputDelegate( DisableInput ),
new object[] { value } );
}
else
inputTextBox.ReadOnly = value;
}
private void inputTextBox_KeyDown( object sender, KeyEventArgs e )
{
try
{
if ( e.KeyCode == Keys.Enter && inputTextBox.ReadOnly == false )
{
writer.Write( "CLIENT>>> " + inputTextBox.Text );
displayTextBox.Text += "\r\nCLIENT>>> " + inputTextBox.Text;
inputTextBox.Clear();
}
}
catch ( SocketException )
{
displayTextBox.Text += "\nОшибка при записи объекта";
}
}
public void RunClient()
{
TcpClient client;
try
{
DisplayMessage( "Подготовка к подключению…\r\n" );
client = new TcpClient();
client.Connect( "127.0.0.1", 50000 );
output = client.GetStream();
writer = new BinaryWriter( output );
reader = new BinaryReader( output );
DisableInput( false );
do
{
try
{
message = reader.ReadString();
DisplayMessage( "\r\n" + message );
}
catch ( Exception )
{
System.Environment.Exit( System.Environment.ExitCode );
}
} while ( message != "SERVER>>> TERMINATE" );
writer.Close();
reader.Close();
output.Close();
client.Close();
Application.Exit();
}
catch ( Exception error )
{
MessageBox.Show( error.ToString(), "Ошибка Соединения",
MessageBoxButtons.OK, MessageBoxIcon.Error );
System.Environment.Exit( System.Environment.ExitCode );
}
}
}
28 мая 2009 в 0:03
В общем вот, вся программа целиком… написал в комментариях что к чему
Серверная часть:
using System;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
public partial class frmServerChatForm : Form
{
publicfrmServerChatForm()
{
InitializeComponent();
}
private Socket connection;
private Thread readThread;
private NetworkStream socketStream;
private BinaryWriter writer;
private BinaryReader reader;
private voidfrmServerChatForm_Load( object sender, EventArgs e )
{
readThread = new Thread( new ThreadStart( RunServer ) );
readThread.Start();
}
private voidfrmServerChatForm_FormClosing(object sender,
FormClosingEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
// делегат, позволяющий вызывать метод DisplayMessage
// от имени потока, отвечающего за создание GUI
private delegate void DisplayMessageDelegate( string message );
// метод, добавляющий клиентское сообщение в поле
// displayTextBox.InvokeRequired возвращает True,
// если запрос идет НЕ от имени потока-создателя
private void DisplayMessage( string message )
{
if ( displayTextBox.InvokeRequired )
{
Invoke( new DisplayMessageDelegate( DisplayMessage ),
new object[] { message } );
}
else
displayTextBox.Text += message;
}
// делегат, позволяющий вызывать метод DisableInput
// от имени потока, отвечающего за создание GUI
private delegate void DisableInputDelegate( bool value );
// метод, запрещающий ввод в поле
// осуществляется по аналогии с DisplayMessage
private void DisableInput( bool value )
{
if ( inputTextBox.InvokeRequired )
{
Invoke( new DisableInputDelegate( DisableInput ),
new object[] { value } );
}
else
inputTextBox.ReadOnly = value;
}
// хэндлер на нажатие клавиш
private void inputTextBox_KeyDown( object sender, KeyEventArgs e )
{
try
{
if ( e.KeyCode == Keys.Enter && inputTextBox.ReadOnly == false )
{
writer.Write( "SERVER>>> " + inputTextBox.Text );
displayTextBox.Text += "\r\nSERVER>>> " + inputTextBox.Text;
if ( inputTextBox.Text == "TERMINATE" )
connection.Close();
inputTextBox.Clear();
}
}
catch ( SocketException )
{
displayTextBox.Text += "\nОшибка при записи объекта";
}
}
28 мая 2009 в 0:03
Серверная часть, продолжение…
// метод, отвечающий за создание и поддержку соединения
public void RunServer()
{
TcpListener listener;
int counter = 1;
try
{
IPAddress local = IPAddress.Parse( "127.0.0.1" );
listener = new TcpListener( local, 50000 );
listener.Start();
while ( true )
{
DisplayMessage( "Ожидание соединения…\r\n" );
connection = listener.AcceptSocket();
socketStream = new NetworkStream( connection );
writer = new BinaryWriter( socketStream );
reader = new BinaryReader( socketStream );
DisplayMessage( "Connection " + counter + " received.\r\n" );
writer.Write( "SERVER>>> Соединение успешно" );
DisableInput( false );
string theReply = "";
do
{
try
{
theReply = reader.ReadString();
DisplayMessage( "\r\n" + theReply );
}
catch ( Exception )
{
break;
}
} while ( theReply != "CLIENT>>> TERMINATE"&&
connection.Connected );
DisplayMessage( "\r\nПользователь отключил соединение\r\n" );
writer.Close();
reader.Close();
socketStream.Close();
connection.Close();
DisableInput( true );
counter++;
}
}
catch ( Exception error )
{
MessageBox.Show( error.ToString() );
}
}
}
27 мая 2009 в 14:05
Нет проси до конца не понимаю. Напиши пожалуйста парочку для этого кода.
25 мая 2009 в 22:03
Нда, что это за автор учебника такой, у которого код в примерах не работает?
Ну тут скорее всего дело в том, что вы выделяете отдельный поток для выполнения различных задач приложения:
readThread = new Thread(new ThreadStart(RunServer));
readThread.Start();
readThread = new Thread(new ThreadStart(RunClient));
readThread.Start();
но, поскольку не рекомендуется делать манипуляции с элементами от имени любого потока, кроме того, что был использован для их создания, то он и выдает ошибку…
Ну а решение этой проблемы – создание нескольких делегатов, которые будут выполнять операцию от имени потока-создателя. Надеюсь понятно объяснил?
25 мая 2009 в 22:02
Dispatcher в помощь. К элементу формы можно обращаться только из того потока, где он был создан.
25 мая 2009 в 22:00
После компиляции выдаёт окно а там
System.InvalidOperation: Недопустимая операция в нескольких потоках: попытка доступа к элнменту управления "displayTextBox" не из того потока, в котором он был создан.
в System.Windows.Forms.Control.get_Handle()
в System.Windows.Forms.Control.set_WindowText(String value)
в System.Windows.Forms.TextBoxBase.set_WindowText(String value)
в System.Windows.Forms.Control.set_Text(String value)
в System.Windows.Forms.TextBoxBase.set_Text(String value)
в System.Windows.Forms.TextBox.set_Text(String value)
в System.RunServer() в Server.cs
24 мая 2009 в 22:03
Насчет первого, сделайте как я уже описал выше.
Ну а предупреждения со 2 по 4 объясняют почему не отображаются элементы. Короче, просто удалите строки их объявления, перетащите нужные из тулбокса на форму и дайте им такие же имена.
24 мая 2009 в 22:02
Предупреждение 1 "System.Net.Sockets.TcpListener.TcpListener(int)" является устаревшим: "This method has been deprecated. Please use TcpListener(IPAddress localaddr, int port) instead. //go.microsoft.com/fwlink/?linkid=14202" Server.cs 80 24
Предупреждение 2 Полю "Server.inputTextBox" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию null Server.cs 13 42
Предупреждение 3 Полю "Server.displayTextBox" нигде не присваивается значение, поэтому оно всегда будет иметь значение по умолчанию null Server.cs 14 42
Предупреждение 4 Полю "Server.component" присвоено значение, но оно ни разу не использовано Server.cs 18 45
а ещё не отображаются элементы
24 мая 2009 в 17:04
если при компиляции ошибок не выдает, то могу предположить, что вот этот код:
listener = new TcpListener(5000);
listener.Start();
стоит заменить на
System.Net.IPAddress local = System.Net.IPAddress.Parse("127.0.0.1");
listener = new System.Net.Sockets.TcpListener(local, 5000);
либо порт 5000 уже занят другим приложением, попробуйте изменить на другое значение
24 мая 2009 в 17:03
Да, лучше сообщения кинь сюда и место возможной проблемы. Весь этот код читать лениво.
24 мая 2009 в 10:02
а что говорит? тут не все телепаты.
24 мая 2009 в 10:01
Клиентская часть
public class Client : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox inputTextBox;
private System.Windows.Forms.TextBox displayTextBox;
private NetworkStream output;
private BinaryWriter writer;
private BinaryReader reader;
private string message = "";
private Thread readThread;
private System.ComponentModel.Container components = null;
public Client()
{
InitializeComponent();
readThread = new Thread(new ThreadStart(RunClient));
readThread.Start();
}
[STAThread]
static void Main()
{
Application.Run(new Client());
}
protected void Client_Closing(object sender, CancelEventArgs e)
{
System.Environment.Exit(System.Environment.ExitCode);
}
protected void inputTextBox_KeyDown(object sender, KeyEventArgs e)
{
try
{
if (e.KeyCode == Keys.Enter)
{
writer.Write("CLIENT»> " + inputTextBox.Text);
displayTextBox.Text += "\r\nCLIENT»> " + inputTextBox.Text;
inputTextBox.Clear();
}
}
catch (SocketException ioe)
{
displayTextBox.Text += "\nError writing object";
}
}
public void RunClient()
{
TcpClient client;
try
{
displayTextBox.Text += "Attempting' connection\r\n";
client = new TcpClient();
client.Connect("localhost", 5000);
output = client.GetStream();
writer = new BinaryWriter(output);
reader = new BinaryReader(output);
displayTextBox.Text += "\r\nGot I/O streams\r\n";
inputTextBox.ReadOnly = false;
do
{
try
{
message = reader.ReadString();
displayTextBox.Text += "\r\n" + message;
}
catch (Exception)
{
System.Environment.Exit(System.Environment.ExitCode);
}
} while (message != "SERVER>>> TERMINATE");
displayTextBox.Text += "\r\nClosing connetion.\r\n";
writer.Close();
reader.Close();
output.Close();
client.Close();
Application.Exit();
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// Client
//
this.ClientSize = new System.Drawing.Size(292, 260);
this.Name = "Client";
this.Text = "Клиент";
this.ResumeLayout(false);
}
}