Показать сообщение отдельно
Старый 16.01.2010, 01:28
alexcon314 вне форума Посмотреть профиль Отправить личное сообщение для alexcon314 Найти все сообщения от alexcon314
  № 10  
Ответить с цитированием
alexcon314
listener

модератор форума
Регистрация: Jun 2006
Сообщений: 3,260
Записей в блоге: 28
Отправить сообщение для alexcon314 с помощью ICQ
Ну вот, еще один примитивный исходник:
Код:
#include <iostream>
#include <process.h>
#include <windows.h>
#include <conio.h>
using namespace std;
#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "mswsock.lib")

unsigned int _stdcall client_thread(void *client_soket)
{
	char Message[200];
	SOCKET Client = (SOCKET)client_soket;
	int len = 0;
	do {
		// Приём сообщения от клиента
		len = recv(Client, Message, 200, 0);

		// Обработка сообщения
		// Если ошибка, выходим из цикла ожидания.
		if(len == SOCKET_ERROR) break;
		
		// Если длина сообщения 0, значит клиент закрыл свой сокет.
		if(len == 0){
			cout << "Client socket closed." << endl;
			break;
		}
		cout << Message << " ";

		// Отправка сообщения клиенту (эхо)
		len = send(Client, Message, strlen(Message) + 1, 0);
		// Если ошибка, выходим из цикла ожидания.
		if(len == SOCKET_ERROR)  break;
		cout << " (echo sent)" << endl;

	} while (1);

	closesocket(Client);
	_endthreadex(0);
	return 0;
}

void main(void) {
	char			hname [64];			// Имя хоста
	WSAData			WSADat;				// Свойства WinSock (результат функции WSAStartup)
	sockaddr_in		server_sin;			// Свойства(адрес) создаваемого сокета сервера
	sockaddr_in		client_sin;			// Свойства(адрес) создаваемого сокета сервера
	SOCKET			Client, Sock;		// Серверный и клиентский сокеты
	WORD			wVersionRequested;	// Версия WinSock
	int				res;
	HANDLE			hThread;
	// Инициализация WinSock 0x0202. Может быть 1.0, 1.1, 2.0, 2.2
	wVersionRequested = MAKEWORD( 2, 2 );
	// WSADat - структура, куда будут занесены результаты инициализации
	if(WSAStartup(wVersionRequested, &WSADat))	
		{cout << "Winsock can't be initialized. Press any key to exit...";	_getch(); return;}
	// Получение имени текущего ПК
	if(gethostname(hname, 64) == SOCKET_ERROR)	
		{cout << "Not host name. Press any key to exit...";	_getch(); return;}
	
	memset (&server_sin, 0, sizeof(server_sin));
	server_sin.sin_family		= AF_INET;	// Тип адреса
	server_sin.sin_addr.s_addr = htonl(INADDR_ANY);	// IP-адрес сервера, здесь 0, можно так: inet_addr("127.0.0.1")
	server_sin.sin_port		= htons(2803);	// Номер порта сервера

	// Создание сокета
	Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
	if (Sock == INVALID_SOCKET)	
		{cout << "Error create socket. Press any key to exit...";	_getch(); return;}

	// Связывание созданного сокета с адресом sin
	res = bind(Sock, (sockaddr*)&server_sin, sizeof(server_sin));
	if (res == SOCKET_ERROR)
		{cout << "Error bind socket. Press any key to exit...";	_getch(); return;} 

	// Прослушивание сокета сервером (для подключения клиента)
	res = listen(Sock, SOMAXCONN);			
	if(res == SOCKET_ERROR)
		{cout << "Error listen socket. Press any key to exit...";	_getch(); return;}
	// Ожидание клиента
	hThread = NULL;
	while(1)
	{
		cout << "Wait of client..." << endl;
		// Стартуем поток обработки клента, если таковой был создан после accept
		if(hThread)
		{
			ResumeThread(hThread);
			CloseHandle(hThread);
			hThread = NULL;
		}
		// Если дождались очередного клиента, делаем аccept
		int sin_len = sizeof(client_sin);
		memset (&server_sin, 0, sin_len);
		Client = accept(Sock, (sockaddr*)&client_sin, &sin_len);	
		if(Client == INVALID_SOCKET)
			{cout << "Error accept client. Press any key to exit...";	_getch(); break;}

		// Пытаемся получить имя хоста клиента, его ip и порт
                       HOSTENT *hst;
                       hst = gethostbyaddr((char *)&client_sin. sin_addr.s_addr, 4, AF_INET);
		char port[6] = "";
		_itoa_s(client_sin.sin_port,port,6,10);
                      // Вывод сведений о клиенте
		printf("New client  %s [%s:%s] has connected!\n", (hst) ? hst->h_name : "", inet_ntoa(client_sin.sin_addr),port);

		// Отправка имени этого компьютера (сервера)
		res = send(Client, hname, strlen(hname)+1, 0);
		if(res == SOCKET_ERROR)
			{cout << "Error send. Press any key to exit...";	_getch(); break;}

		cout << " Start client thread...";
		
		// Создаем поток обработки сообщений клиента, стартуем его чуть позже в случае успеха
		hThread = (HANDLE)_beginthreadex(NULL, 0, client_thread, (void*)Client, CREATE_SUSPENDED, NULL);
		if(!hThread)
			{cout << "Error start client thread. Press any key to exit...";	_getch(); break;}

		cout << " ok." << endl;
	}
	CloseHandle(hThread);
	closesocket(Sock);
	WSACleanup();
}
Идея, как видите в том, что "многопользовательский сервер" обрабатывает каждый коннект в отдельном потоке.
Вообще, есть еще такое интересное понятие, как пул потоков, рекомендую ознакомиться.
Цитата:
Каким образом принятые данные из сокет сервера можно преобразовать в переменные и чтобы во флеше все выстроилось как надо
А вот это уже зависит только от того, как вы сами захотите передавать данные: это может быть строка с разделителями, xml или просто любая последовательность байтов.
Цитата:
каким эт образом можно различить юзеров, да даже бонально крестики нолики как свф поймет когда ходит юзер1 а когда юзер2
ну, видимо, принимаемые данные должны содержать не только информацию о ходе игры, но и идентификатор пользователя этот ход совершившего.

UPD:
немного причесал исходник.
это читать для дальнейшего понимания, что есть непримитивный исходник.


Последний раз редактировалось alexcon314; 18.01.2010 в 12:39.