Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > C++ > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail


Ответ
 
Опции темы
Старый 14.08.2015, 15:29   #1
Drago56
Форумчанин
 
Регистрация: 13.12.2010
Сообщений: 91
Репутация: 8
По умолчанию консольный чат

подскажите куда ставить код select() в сервер или клиент, или туда и сюда.Происходит зависание в клиенте на recv, программа ожидает ввода от клиента и поэтому если сервер присылает сообщение от других клиентов, они не приходят потому что программа стоит на recv. Пробывал тока на сервер не работает.
сервер.
Код:

#include <iostream>
#pragma comment( lib, "ws2_32.lib" )
#include<windows.h>
#include<conio.h>
#define PORT 666 

SOCKET conect;//подключат пользователя, и передает в конектион
SOCKET* connections;
SOCKET server1;//подклчение
int kol=0;

char* s; 
using namespace std;

void funck(int ip)
{
	 char* buff=new char[1024];
     while (1)
     {
     	memset(buff,0,sizeof(buff));
        if(recv(connections[ip],buff,sizeof(buff),0))
        {
        	cout << buff << std::endl;
            for(int i=0;i<=kol;i++) 
			send(connections[i],buff,strlen(buff),0);	
      
	    }
	
	}
	kol--;
    printf("-отключение [%s]\n",s);// PRINTNUSERS
   delete buff;
}

int main()
{
	WSADATA dat;
	WORD versya;
	versya=MAKEWORD(2,0);
	connections=(SOCKET*)calloc(64,sizeof(SOCKET));
	printf("Сервер");
	
	if(WSAStartup(versya,&dat))
	{
		printf("Ошибка ");
        return -1;
	}
	
	 if ((server1=socket(AF_INET,SOCK_STREAM,0))<0)//
    {
      printf("Ошибка при создании socket %d\n",WSAGetLastError());
      WSACleanup();//удаляем сокет
      return -1;
    }
    
	sockaddr_in adr;
	adr.sin_family=AF_INET;
	adr.sin_port=htons(PORT);
	adr.sin_addr.s_addr=0;//IPPROTO_TCP;
	
  //  server1=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (bind(server1,(sockaddr *) &adr,sizeof(adr)))//подключение сокета к комуникационной среде(успех=0,провал -1).Присваивает сокету
    //локальный адресс.Кароче присвоение имени сокету из пространства
    {
      printf("\nОшибка присвоение имени сокету bind %d\n",WSAGetLastError());
      closesocket(server1); 
      WSACleanup();
      return -1;
    }

	if (listen(server1, 20))//SOMAXCONN))//ожидание запроса от клиента,20 максимальное число очереди
    {
      printf("\nОшибка ожидание клиента %d\n",WSAGetLastError());
      closesocket(server1);
      WSACleanup();
      return -1;
    }
	printf("\nОжидание соединения\n");
	
	sockaddr_in cl_addr;
	int cl_addr_size=sizeof(cl_addr);
	char buf_con[]="Подключение успешно\n";
	while((conect=accept(server1,(sockaddr*)&cl_addr,&cl_addr_size)))
	{
	    // if(accept(server1,(sockaddr*)&cl_addr,&cl_addr_size)<0) break;
		 connections[kol]=conect;
		 printf("[%s] новый пользователь!\n",inet_ntoa(cl_addr.sin_addr));
		 s=new char[cl_addr_size];
         s=inet_ntoa(cl_addr.sin_addr);//чтобы потом при закрытии показывало адрес компа
         send(connections[kol],buf_con,strlen(buf_con),0);	
         kol++;
         CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)funck,(LPVOID)(kol-1),NULL,NULL);
	}
	
	
	
	return 0;
}

Клиент
Код:

#include <iostream>
#pragma comment( lib, "ws2_32.lib" )
#include<windows.h>
#include<conio.h>
#define PORT 666
#define SERVERADDR "192.168.0.104"
 
  int main(int argc, char* argv[])
  {
    char buff[1024];
    printf("TCP клиент\n");
    WSADATA wsaData;//даные о сокете
    WORD Version;// запрашиваемая версия винсок
    Version = MAKEWORD (2, 0);      // задаем версию
     if (WSAStartup(Version,&wsaData)) 
    {
      printf("Ошибка WSAStart %d\n",WSAGetLastError());
      return -1;
    }
 
    SOCKET my_sock;
    my_sock=socket(AF_INET,SOCK_STREAM,0);
    if (my_sock < 0)
    {
      printf("Socket() error %d\n",WSAGetLastError());
      return -1;
    }

    sockaddr_in hos_addr;
    hos_addr.sin_family=AF_INET;
    hos_addr.sin_port=htons(PORT);
    HOSTENT *hostt;
 
    if (inet_addr(SERVERADDR)!=INADDR_NONE)//конвертирует строку в значение,инхандер нон это ошибка
      hos_addr.sin_addr.s_addr=inet_addr(SERVERADDR);
    else
   
      if (hostt=gethostbyname(SERVERADDR))

      ((unsigned long *)&hos_addr.sin_addr)[0]=((unsigned long **)hostt->h_addr_list)[0][0];//??????????????
      else
      {
        printf("Неверный адресс %s\n",SERVERADDR);
        closesocket(my_sock);
        WSACleanup();
        return -1;
      }
 
    if (connect(my_sock,(sockaddr *)&hos_addr,sizeof(hos_addr)))
    {
      printf("Connect error %d\n",WSAGetLastError());
      return -1;
    }
 
    printf("Сoединение с ? %s установленно\n\n",SERVERADDR);
      
   // DWORD ID;

    int nsize;
    
    while(1)
    { 	
     if(nsize = recv(my_sock,&buff[0], sizeof(buff),0) !=SOCKET_ERROR){  
      buff[nsize]=0;
      printf("S=>C:%s",buff);
      printf("S<=C:"); fgets(&buff[0],sizeof(buff)-1, stdin);
      // коректный выход
      if (!strcmp(&buff[0],"quit\n"))
      {
        printf("Exit...");
        closesocket(my_sock);
        WSACleanup();
        return 0;
      }
}
      send(my_sock,&buff[0],strlen(&buff[0]),0);
    }
 
    printf("Recv error %d\n",WSAGetLastError());
    closesocket(my_sock);
    WSACleanup();
    return -1;
  }


Последний раз редактировалось Drago56; 14.08.2015 в 15:31.
Drago56 вне форума   Ответить с цитированием
Старый 14.08.2015, 15:55   #2
waleri
Профессионал
 
Регистрация: 13.07.2012
Адрес: Нижний Новгород
Сообщений: 5,562
Репутация: 1743
По умолчанию

Так запустите в клиенте поток для приема данных, а-ля сервер, вот и все.

А по-хорошему, надо и там и там использовать select и не разводить потоки.

Кроме того, у вас и сервак зависнет, если какой нибудь из клиентов перестанет принимать данные.
waleri вне форума   Ответить с цитированием
Старый 15.08.2015, 14:36   #3
Drago56
Форумчанин
 
Регистрация: 13.12.2010
Сообщений: 91
Репутация: 8
По умолчанию

а словами можно описать алгоритм в каких местах правильно использовать селект
Drago56 вне форума   Ответить с цитированием
Старый 15.08.2015, 14:46   #4
Stilet
Белик Виталий :)
Профессионал
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Адрес: Украина, Донецкая область, г. Краматорск
Сообщений: 57,957
Репутация: 6832
По умолчанию

На словах... Ну если в общем:
Код:

  while(1)
    { 	
     if(!select(my_sock,....)) continue;
     if(nsize = recv(my_sock,&buff[0], sizeof(buff),0) !=SOCKET_ERROR){  
....
   }

Почитай тут: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx о подробностях параметров. Там указываешь какое направление промониторить (входящие - readfds или исходящие пакеты - writefds) и в какой таймаут.
__________________
I'm learning to live...
Stilet вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Консольный колькулятор. stdio Общие вопросы C/C++ 12 01.03.2012 23:49
Консольный калькулятор 999Corp999 Помощь студентам 2 17.01.2011 18:17
Консольный архиватор Alex Cones Софт 12 14.04.2010 12:53
Консольный сервер на C++ Builder BleStaR C++ Builder 3 20.01.2010 21:16
код из С++ в чисто консольный С АртёмМ Помощь студентам 3 18.10.2009 16:06


23:17.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru