Господа, убедительная просьба — не могли бы вы поделиться кусочком кода, связанным с применением Сокетов в C# или в VB.NET.
Бьёмся — ничего не получается.
Задача-минимум — отправить некий текст и затем получить его.
Оба сокета созданы на локальной машине, порты у обоих одинаковые.
После этого выводим состояние сокетов — первый Connected = False, второй — Connected = True (т.е. тот, который был в ожидании, он так и не перешел в состояние соединения).
При этом Если не переводить первый в ожидание, второй тоже не соединяется.
Всё заканчивается плохо. Если что-то закончилось хорошо — значит оно еще не закончилось.
Здравствуйте, Unforgiver, Вы писали:
U>Господа, убедительная просьба — не могли бы вы поделиться кусочком кода, связанным с применением Сокетов в C# или в VB.NET.
Поиск chat*.* в директории со студией делали? Там есть пара готовых примеров с сокетами.
Здравствуйте, Andrbig, Вы писали:
A>Здравствуйте, Unforgiver, Вы писали:
U>>Господа, убедительная просьба — не могли бы вы поделиться кусочком кода, связанным с применением Сокетов в C# или в VB.NET.
A>Поиск chat*.* в директории со студией делали? Там есть пара готовых примеров с сокетами.
Там не с сокетами, а как-то по другому сделано.
Мы прошли дальше
Разделили сокеты на разные компы — теперь один слушает, второй соединяется.
И вот тут беда — слушающего мы не можем перевести в состояние "соединенный" ...
КАК ЭТО СДЕЛАТЬ ?
Грубо говоря, сокет в состоянии ожидания
If ???? then socket.перевести в состояние соединения
А вот что вместо ???? поставить ?
Всё заканчивается плохо. Если что-то закончилось хорошо — значит оно еще не закончилось.
Здравствуйте, Unforgiver, Вы писали:
U>Господа, убедительная просьба — не могли бы вы поделиться кусочком кода, связанным с применением Сокетов в C# или в VB.NET. U>Бьёмся — ничего не получается. U>Задача-минимум — отправить некий текст и затем получить его.
U>Создаем два сокета, потом пишем
U>socket1.Listen(1) U>socket2.Connect(L) (L — адрес, определенный заранее).
U>Оба сокета созданы на локальной машине, порты у обоих одинаковые.
U>После этого выводим состояние сокетов — первый Connected = False, второй — Connected = True (т.е. тот, который был в ожидании, он так и не перешел в состояние соединения). U>При этом Если не переводить первый в ожидание, второй тоже не соединяется.
Вот, недавно писал в универе таску по криптографии с использованием Socket'ов, выложу, может пригодиться. Там все достаточно просто.
User.cs
using System;
using System.Net;
using System.Net.Sockets;
namespace Iae.Nsu.Crypto.ElGamal
{
/// <summary>
/// Класс пользователя шифром Эль-Гамаля.
/// </summary>public class User
{
public User(int prime)
{
this.p_ = prime;
System.Random rand = new Random();
int n, x, y;
int t = this.p_-1;
do
{
// c_ выбираем случайным образомthis.c_ = (int)System.Math.Abs(rand.Next(t));
// проверяем что бы НОД(c_, (p_-1)*(q_-1)) = 1
CryptoLibrary.Math.EuclidAlgoritm(this.c_, t, out n, out x, out y);
// если не равняется выбираем новое c_
} while(n != 1 || this.c_ < 2);
this.g_ = CryptoLibrary.Math.FindGenerativeElement(this.p_);
this.d_ = CryptoLibrary.Math.PowerByModule(this.g_, this.c_, this.p_);
}
private Socket sock;
private int p_;
private int c_;
private int d_;
private int g_;
protected string name_;
/// <summary>
/// Имя пользователя.
/// </summary>public string Name
{
get
{
return this.name_;
}
set
{
this.name_ = value;
}
}
/// <summary>
/// Шифруем сообщение <b>message</b> в поток байт используя
/// открытый ключ опонента <b>d</b>.
/// </summary>
/// <param name="message">Сообщение для пересылки.</param>
/// <param name="d">Несекретная информация опонента.</param>
/// <returns>Зашифрованное сообщение.</returns>public byte [] EncodeMessage(string message, int d)
{
int len = message.Length;
char [] chs = message.ToCharArray();
int [] its = new int[len+1];
byte [] bts = new byte[(len+1)*4];
int r__;
Random rand = new Random();
int k = rand.Next(2, this.p_-1);
r__ = CryptoLibrary.Math.PowerByModule(this.g_, k, this.p_);
its[0] = r__;
for (int i = 0; i < len; i++)
{
its[i+1] = CryptoLibrary.Math.PowerByModule(d, k, this.p_);
its[i+1] = CryptoLibrary.Math.PowerByModule(its[i+1]*chs[i], 1, this.p_);
}
for (int i = 0; i <= len; i++)
{
bts[i*4+0] = (byte)(its[i]%256); its[i] /= 256;
bts[i*4+1] = (byte)(its[i]%256); its[i] /= 256;
bts[i*4+2] = (byte)(its[i]%256); its[i] /= 256;
bts[i*4+3] = (byte)(its[i]%256); its[i] /= 256;
}
return bts;
}
/// <summary>
/// Дешифровываем сообщение из потока байт <b>bytes</b> из
/// которых полезных <b>length</b> байт.
/// </summary>
/// <param name="bytes">Зафирванное сообщение.</param>
/// <param name="length">Кол-во полезных байт.</param>
/// <returns>Дешифрованное сообщение.</returns>public string DecodeMessage(byte [] bytes, int length)
{
int len = length / 4;
char [] chs = new char[len];
int [] its = new int[len];
int r__ = 0;
for (int i = 0; i < len; i++)
{
its[i] += bytes[i*4+3]; its[i] *= 256;
its[i] += bytes[i*4+2]; its[i] *= 256;
its[i] += bytes[i*4+1]; its[i] *= 256;
its[i] += bytes[i*4+0];
if (i == 0)
{
r__ = its[0];
}
else
{
int t = CryptoLibrary.Math.PowerByModule(r__, this.p_-1-this.c_, this.p_);
chs[i-1] = (char)CryptoLibrary.Math.PowerByModule(t*its[i], 1, this.p_);
}
}
return new string(chs);
}
/// <summary>
/// Принимаем сообщение. Открываем сокет на порт <b>port</b>.
/// Ждем установления соединения. Затем высылаем свой открытый ключ.
/// Ожидаем сообщение. Дешифруем его.
/// </summary>
/// <param name="port">Порт.</param>public void WaitMessage(int port)
{
byte [] bts = new byte[1024];
int t = this.d_;
int len;
IPAddress ipAddress = new IPAddress(0);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Bind(new IPEndPoint(ipAddress, port));
sock.Listen(5);
System.Console.WriteLine("{0}: Ожидаем запрос на установку соединения.", this.name_);
Socket s = sock.Accept();
System.Console.WriteLine("{0}: Соединение установленно.", this.name_);
System.Console.WriteLine("{0}: Отправляем несекретные данные.", this.name_);
for (int i = 0; i < 4; i++)
{
bts[i] = (byte)(t%256); t/=256;
}
s.Send(bts, 4, SocketFlags.None);
System.Console.WriteLine("{0}: Ожидаем сообщение.", this.name_);
len = s.Receive(bts);
System.Console.WriteLine("{0}: Сообщение успешно принято.", this.name_);
System.Console.WriteLine("{0}: Сообщение дешифруется.", this.name_);
string message = this.DecodeMessage(bts, len);
System.Console.WriteLine("{0}: Полученно сообщение:: {1}", this.name_, message);
}
/// <summary>
/// Отправляем сообщение <b>message</b> на <b>IPaddress:port</b>.
/// Устанавливаем соединение. Получаем публичный ключ. Шифруем.
/// Отравляем.
/// </summary>
/// <param name="IPaddress">Адрес опонента.</param>
/// <param name="port">Его порт.</param>
/// <param name="message">Сообщение для отправки.</param>public void SendMessage(string IPaddress, int port, string message)
{
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(IPaddress), port);
Socket s = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
byte [] bytes = new byte[4];
s.Connect(ipe);
if (s.Connected)
{
System.Console.WriteLine("{0}: Соединение установленно.", this.name_);
System.Console.WriteLine("{0}: Ожидаем несекретные данные опонента.", this.name_);
s.Receive(bytes);
int dFriend = (((bytes[3]*256 + bytes[2])*256 + bytes[1])*256 + bytes[0]);
System.Console.WriteLine("{0}: Производим шифровку и пересылку сообщения.", this.name_);
if(s.Send(this.EncodeMessage(message, dFriend)) == (message.Length+1)*4)
{
System.Console.WriteLine("{0}: Сообщение успешно посланно.", this.name_);
}
else
{
System.Console.WriteLine("{0}: Ошибка при посылке сообщения.", this.name_);
}
}
else
{
System.Console.WriteLine("{0}: Ошибка при установлении соединения.", this.name_);
}
}
}
}
Main.cs
using System;
using Iae.Nsu.Crypto.CryptoLibrary;
namespace Iae.Nsu.Crypto.ElGamal
{
/// <summary>
/// Summary description for Class1.
/// </summary>class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
User a = new User(5851);
a.Name = "Alice";
User b = new User(5851);
b.Name = "Bob";
System.Console.Write("Для принятия сообщения введите 1, для отправки 2: ");
int s = System.Console.Read();
System.Console.Read(); System.Console.Read();
if (s == (int)'1')
{
System.Console.Write("Введите номер порта для принятия сообщения: ");
int port = Int32.Parse(System.Console.ReadLine());
a.WaitMessage(port);
}
else
{
System.Console.Write("Введите IP адрес назначения сообщения: ");
string IPaddress = System.Console.ReadLine();
System.Console.Write("Введите номер порта для отправки сообщения: ");
int port = Int32.Parse(System.Console.ReadLine());
System.Console.Write("Введите сообщение для отправки: ");
string message = System.Console.ReadLine();
b.SendMessage(IPaddress, port, message);
}
}
}
}
ie>Вот, недавно писал в универе таску по криптографии с использованием Socket'ов, выложу, может пригодиться. Там все достаточно просто.
Спасибо. Соединились
Просто раньше в VB 6 был контрол — WinSock, у которого было событие "Connection_Request". Типа когда на него запрос приходил, оно инициировалось.
А теперь контрола нет, и события такого соответственно тоже.
Так что — спасибо, что помог разобраться.
Удачи.
Всё заканчивается плохо. Если что-то закончилось хорошо — значит оно еще не закончилось.
Спасибо всем за присланные сообщения, однако возникает другая проблема:
Все описанные примеры работают с консолью (а мне надо было сразу работать с формой). Ну это не беда.
Проблема в том, что после написания
sock.Bind(...);
sock.Listen(...);
система подвисает до тех пор, пока на этот сокет не придет запрос о соединении.
Дальше идёт
Socket NewSock = sock.Accept();
и эта строка срабатывает, что логично, после того, как придет запрос (connect) от клиента.
Но вот что делать с Listen ? Как заставить приложения обрабатывать другие прерывания.
В VB 6 была функция DoEvents, но она вставлялась в цикл, чтобы во время его выполнения обрабатывать другие запросы.
Тут и функции нет (может быть она как-то по другому объявляется ?) да и цикла я не вижу.
Помогите победить.
Заранее спасибо.
Всё заканчивается плохо. Если что-то закончилось хорошо — значит оно еще не закончилось.
Re: Socket
От:
Аноним
Дата:
08.10.04 12:29
Оценка:
Как заставить приложения обрабатывать другие прерывания>
Вынесите ожидание в отдельный поток. И там вызывайте callbaсk как-нибудь.
А фунция есть — Application.ProcessEvents(), если не путаю. Но это грязный путь, говорят. Поток лучше.
Здравствуйте, Unforgiver, Вы писали:
U>Но вот что делать с Listen ? Как заставить приложения обрабатывать другие прерывания.
Использовать асинхронные сокеты ?
Или как вариант .SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 3000); — но мне кажется это плохое решение.
Кстати, есть еще такая вещь, как Mutiplexed Sockets:
Just as in Unix, the Socket class provides the Select() method. This method is used to multiplex multiple Socket instances to watch for the ones that are ready to be read or written to. In C#, however, the Select() method is used somewhat differently. Here is the format of the Select() method:
Select(IList read, IList write, IList error,
int microseconds)
The read, write, and error parameters are IList objects, which are arrays that contain created sockets to monitor. The microseconds parameter defines the amount of time (in microseconds) the Select() method will wait for the events to happen.
The following is a small code fragment showing how the Select() method can be used:
ArrayList socketList = new ArrayList(5);
SocketList.Add(sock1);
SocketList.Add(sock2);
Socket.Select(socketList, null, null, 1000);
byte[] buffer = new byte[1024];
for (i = 0; i < socketList.Length - 1; i++)
{
socketList[i].Receive(buffer);
ConsoleWriteLine(Encoding.ASCII.GetString(buffer));
}
Notice that the Select() method will monitor both sock1 and sock2 for incoming data. If no data is present on either socket, the Receive() method will not block the program.
Здравствуйте, Аноним, Вы писали:
А> Вынесите ожидание в отдельный поток. И там вызывайте callbaсk как-нибудь. А>А фунция есть — Application.ProcessEvents(), если не путаю. Но это грязный путь, говорят. Поток лучше.
Спасибо, попробую. С потоками надо еще разобраться будет. Пока не сталкивался с ними.
Всё заканчивается плохо. Если что-то закончилось хорошо — значит оно еще не закончилось.
Здравствуйте, Unforgiver, Вы писали:
U>Спасибо всем за присланные сообщения, однако возникает другая проблема: U>Все описанные примеры работают с консолью (а мне надо было сразу работать с формой). Ну это не беда. U>Проблема в том, что после написания
U>sock.Bind(...); U>sock.Listen(...);
U>система подвисает до тех пор, пока на этот сокет не придет запрос о соединении.
Юзай, асинхронные сокеты:
// где-то в коде
//...
sock.Bind(...);
sock.Listen(...);
sock.BeginAccept(AsyncCallback(AcceptCallback), sock);
//...public static void AcceptCallback(IAsyncResult ar)
{
Socket sock = (Socket)ar.AsyncState;
Socket acceptSock = sock.EndAccept(ar);
// тут дальше работаешь с acceptSock
}
Как узнать при помощи Сокетов, имеются ли ожидающие запросы на подключение?
s.Bind(ep2);
s.Listen(1);
s = s.Accept(); // На этом месте виснит программа если нет входящих запросов
В классе TcpListener есть метод Pending, как раз то что надо... Но не хотелось бы лишний класс вводить.
Здравствуйте, TechnoMen, Вы писали:
TM>Как узнать при помощи Сокетов, имеются ли ожидающие запросы на подключение? TM>s.Bind(ep2); TM>s.Listen(1); TM>s = s.Accept(); // На этом месте виснит программа если нет входящих запросов
TM>В классе TcpListener есть метод Pending, как раз то что надо... Но не хотелось бы лишний класс вводить.
Для сокетов используй Poll.
if (s.Poll(waitingTimeout, SelectMode.SelectRead))
{
sAccepted = s.Accept();
}