Новичок
Профиль
Группа: Участник
Сообщений: 1
Регистрация: 25.5.2010
Репутация: нет Всего: нет
|
Здравствуйте! Я пишу сервер (под Windows, C#, Visual Studio 2008) для удаленного управления роботом (Robotino). Столкнулся с вот какой трудностью. Сервер написал с использованием асинхронных функций BeginAccept, BeginReceive и прочих. Мой клиент отлично соединяется с сервером в локальной сети. Но по заданию, он должен работать через интернет. Начал тестировать в инете. Использовал 2 способа: 1) приложение-сервер запускал на компьютере с выделенным IP; 2) используя Hamachi (позволяет создать локальную сеть поверх интернета), пытался соединиться клиентом через интернет с моим удаленным сервером Robotino. То есть как будто мы в одной сети. [этот способ походит, когда нет выделенного IP] Пробовал разные порты - результат один и тот же: ошибка " Запрос на отправку или получение данных (when sending on a datagram socket using a sendto call) no address was supplied". Вот что странно - при соединении начальный коннект происходит - на сервер приходят имя пользователя и пароль. А дальше - дисконнект. У сервера вылетает: "Удаленный пользователь разорвал соединение". Может что-то во времени ожидания? (пинг был 60 мс) Как я уже упоминал, в локальной все работает отлично. Очень надеюсь на вашу помощь! Фрагмент кода клиента Код | try { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Parse(txtServerIP.Text);
int tPort = Convert.ToInt32(txtServerPort.Text); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, tPort);
clientSocket.BeginConnect(ipEndPoint, new AsyncCallback(OnConnect), null);
byteData = new byte[1024];
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), null); } catch (Exception ex) { MessageBox.Show(ex.Message, "Сlient error", MessageBoxButtons.OK, MessageBoxIcon.Error); // вот тут и имеем Exception }
|
Если пригодится - продолжение кода Код | private void OnReceive(IAsyncResult ar) { try { clientSocket.EndReceive(ar); Data msgReceived = new Data(byteData); switch (msgReceived.cmdCommand) { case Command.Login: //проверка: принял ли сервер данные пользователя if (!(msgReceived.strMessage == "Error Username or Password")) { strName = txtName.Text; DialogResult = DialogResult.OK; Close(); } else { strName = txtName.Text; MessageBox.Show( "Error Username or Password. Please, input incorrect data!","SGSClientTCP: "+strName,MessageBoxButtons.OK,MessageBoxIcon.Error); } break; } } catch (ObjectDisposedException) { } catch (Exception ex) { MessageBox.Show(ex.Message, "СlientTCP: " + strName, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void OnSend(IAsyncResult ar) { try { clientSocket.EndSend(ar); } catch (Exception ex) { MessageBox.Show(ex.Message, "44SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void OnConnect(IAsyncResult ar) { try { clientSocket.EndConnect(ar); //Установлено соединение, произведем вход на сервер Data msgToSend = new Data (); msgToSend.cmdCommand = Command.Login; msgToSend.strName = txtName.Text; msgToSend.strMessage = txtPass.Text;
byte[] b = msgToSend.ToByte (); //Отослать сообщения на сервер clientSocket.BeginSend(b, 0, b.Length, SocketFlags.None, new AsyncCallback(OnSend), null); } catch (Exception ex) { MessageBox.Show(ex.Message, "55SGSclient", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
|
А это - фрагмент кода сервера: Код | try { //Используем TCP-сокеты serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Назначаем любой IP машины и слушаем порт 1200 int tPort = Convert.ToInt32(toolStripTextBoxPort.Text); IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, tPort);
//Связываем(Bind) и слушаем сеть serverSocket.Bind(ipEndPoint); serverSocket.Listen(1000);
//Прием входящего соединения serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); statusLabel.Text = "Статус: сервер включен."; } catch (Exception ex) // Обработка исключения { MessageBox.Show(ex.Message, "SGSserverTCP [1]", MessageBoxButtons.OK, MessageBoxIcon.Error); } |
Код | private void OnAccept(IAsyncResult ar) { try { Socket clientSocket = serverSocket.EndAccept(ar);
//Начинаем прослушивание, ожидая других клиентов serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
//После подключения клиент, начаем получать команды от него clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } catch (Exception ex) //Обработка исключений { MessageBox.Show(ex.Message, "SGSserverTCP [2]", MessageBoxButtons.OK, MessageBoxIcon.Error); } } |
При попытке соединения сервер выдает: MessageBox.Show(ex.Message, "SGSserverTCP [3]", MessageBoxButtons.OK, MessageBoxIcon.Error); Пользователь разорвал соединение Код | private void OnReceive(IAsyncResult ar) { try { Socket clientSocket = (Socket)ar.AsyncState; clientSocket.EndReceive(ar);
// Преобразование массива байт, полученных от пользователя, // в форму объекта Data Data msgReceived = new Data(byteData);
//Этот объект мы будем отсылать на запросы пользователей Data msgToSend = new Data();
byte[] message; bool loggedOn = false;
// Если сообщение является Войти, выход, или простое текстовое сообщение, // то при отправке другим пользователям, тип сообщения остается неизменным msgToSend.cmdCommand = msgReceived.cmdCommand; msgToSend.strName = msgReceived.strName;
if (msgReceived.cmdCommand == Command.Login) { foreach (AccountsData Account in DataBase) { if (Account.userName == msgReceived.strName && Account.userPass == msgReceived.strMessage) { loggedOn = true; break; } }
if (loggedOn) { // Когда пользователь входит на сервер, мы добавляем его // в список клиентов ClientInfo clientInfo = new ClientInfo(); clientInfo.socket = clientSocket; clientInfo.strName = msgReceived.strName; clientInfo.activ = true; clientList.Add(clientInfo); // Готовим текст сообщения для массовой рассылки msgToSend.strMessage = "*** " + msgReceived.strName + " has joined server"; //!!! тут добавить изменение флага в массиве авторизации message = msgToSend.ToByte(); clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientSocket); } else { msgToSend.cmdCommand = Command.Login; msgToSend.strMessage = "Error Username or Password"; message = msgToSend.ToByte(); clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientSocket); //clientSocket.Close(); }
}
bool AcceptClient = false; foreach (ClientInfo client in clientList) { if (client.socket == clientSocket && client.activ == true) { AcceptClient = true; break; } }
if (AcceptClient) { switch (msgReceived.cmdCommand) // Обработка полученной команды { case Command.Logout: // Если пользователь хочет выйти из сервера, мы ищем его // в списке клиентов и закрываем соответствующие связи int nIndex = 0; foreach (ClientInfo client in clientList) { if (client.socket == clientSocket) { clientList.RemoveAt(nIndex); break; } ++nIndex; // Отсчитываем индекс в цикле foreach } clientSocket.Close(); //Массовая рассылка - клиент вышел msgToSend.strMessage = "*** " + msgReceived.strName + " has left server"; break;
case Command.Message: // Готовим текст сообщения, который мы будет транслировать для всех пользователей msgToSend.strMessage = msgReceived.strName + ": " + msgReceived.strMessage; MF.textBox1.Text = msgReceived.strMessage; /* if (msgReceived.strMessage == "GO!") { MF.textBox1.Text = "GO!"; //MF.Visible = true; msgReceived.strMessage = "OK!"; } if (msgReceived.strMessage == "FWD") { MF.textBox1.Text = "FWD"; MF.Visible = true; msgReceived.strMessage = "OK! FWD"; } */ break;
case Command.List: // Отсылаем имена всех присутствующих пользователей новому пользователю msgToSend.cmdCommand = Command.List; msgToSend.strName = null; msgToSend.strMessage = null;
// Собираем имена всех пользователей foreach (ClientInfo client in clientList) { //Для упрощения, используем маркер разделения имен пользователей msgToSend.strMessage += client.strName + "*"; } message = msgToSend.ToByte();
//Отсылаем имена всех пользователей clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientSocket); break; }
if (msgToSend.cmdCommand != Command.List) //Не List, так как List уже отослан { message = msgToSend.ToByte();
foreach (ClientInfo clientInfo in clientList) { if (clientInfo.socket != clientSocket || msgToSend.cmdCommand != Command.Login) { // Если не команда Login, то отсылаем всем, // кроме приславшего (clientSocket) clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientInfo.socket); } }
txtLog.Text += DateTime.Now.ToString() + "> " + msgToSend.strMessage + "\r\n"; }
//Если пользователь не выходит, значит мы его слушаем if (msgReceived.cmdCommand != Command.Logout) { //Начинаем слушать пользователя clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); }
} } catch (Exception ex) { MessageBox.Show(ex.Message, "SGSserverTCP [3]", MessageBoxButtons.OK, MessageBoxIcon.Error); } } |
|