4 sloty(4 miejsca/osoby)

0

Na poczatku chciałbym podziekowac johnemu Bravo za wytlumaczenie, zrozumialem juz o co chodzi, Dziękuję :) Teraz bym chcial od was się dowiedzieć w jaki sposob mogę zrobic żeby do servera dołaczylo 4 osoby... Zaczełem nowy projekt, Server w consoli i klient w oknie... I niewiem jak zrobić, że tekst klienta dochodzi do servera(consoli), a server(consola) to wszystkim pokazuje ten tekst wysylajac do ich okienek tekstowych.... W kliencie zrobilem mozliwosc wpisania ip do polaczenia... Ale chcialbym teraz przejsc do tekstu, a pozniej nawet jakiejs gry... Bo wczesniej mały niewypal w moim kodzie ;P

Podsumujac, Chcialbym aby:
-4 sloty do servera
-tekst wysylany z klienta(okienka) do servera(consoli, server odbiera i wysyla do reszty klientow(okienka)...

Bardzo bym prosil o jakiś kod przykladowy, bo inaczej mi to w banie nie wejdzie... ;)

0

Hm, ja bym zabrał się za to w ten sposób: (jedna z wielu możliwych dróg, ale mnie przynajmniej wydaje sie sensowna, na razie częśc serwera z nieograniczoną ilością slotów (dla gry to chyba lepsze))

public class Account
{
	public System.Net.Sockets.Socket TCPEngine;
	public String Nick;

	internal void SendMessage(string msg)
	{
		TCPEngine.Send(Encoding.UTF8.GetBytes(msg));
		/* Wypadałoby zrobić to w ten sposób, żeby każdy rodzaj
		 * wiadomości miał swój własny pakiet, dziedziczący po jakimś
		 * interfejsie, i potem po prostu napisać metodę
		 * SendPacket, która by go wysyłała, (co prawda pomieszanie nieco MVC,
		 * ale to tylko schemat
		 */
	}
}

internal class Game
{
	System.Net.Sockets.Socket MainListener;
	List<Account> Accounts = new List<Account>();
	Boolean Server_Running = false;

	void BroadcastMessage(string msg, Account UserAccount)
	{
             // UserAccount po to, żeby można potem pisać, od kogo wyszła dana wiadomość
		foreach (Account acc in Accounts)
		{
			acc.SendMessage(msg);
		}
	}

	Account CreateAccount(System.Net.Sockets.Socket sock)
	{
		Account result = new Account();
		result.TCPEngine = sock;
		return result;
	}

	void WaitForConnection()
	{
		while (Server_Running)
		{
			System.Net.Sockets.Socket accepted = MainListener.Accept();
			Account CreatedAccount = CreateAccount(accepted);
			Accounts.Add(CreatedAccount);
			System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ServiceAccount));
			thread.Start(CreatedAccount);
		}

	}
	void ServiceAccount(Account acc)
	{
		byte[] received_data;
		while (Server_Running /* i jakieś dodatkowe warunki */)
		{
			if (acc.TCPEngine.Available > 0)
			{
				received_data = new byte[acc.TCPEngine.Available];
				acc.TCPEngine.Receive(received_data);
				string msg = TranslateData(received_data);
				/* Obsłuż odebrane dane, przeczytaj nagłówek wiadomości
				 * sprawdź czy wszystko ok, sprawdź jaka to wiadomość
				 * , jeżeli to wiadomość do innych graczy to:
				 * (Metoda TranslateData musi być utworzona)
				 */
				string msg = TranslateData(received_data);
				BroadcastMessage(msg, acc);
			}
		}
	}
}

Dla każdego przyłączającego się klienta tworzysz mu albo osobny wątek, albo korzystasz z metod xxxAsync (na MSDN są przykłady, rozwiązanie wydajniejsze).
Następnie w tym wątku uruchamiasz pętle i czekasz, aż przyjdą dane, te dane w jakiś sposób obsługujesz (<url=www.maciejaniserowicz.com>www.maciejaniserowicz.com/ - tu jest ciekawy przykład rozwiązania klient-serwer</url>).
Lepszym rozwiązaniem od mojego byłoby napisanie klasy Pokoju lub czegos w tym guście, ponieważ jeśli chciałbyś rozgraniczyć, do kogo ma iść dana wiadomość, nie mógłbyś tak po prostu iterować po liście.
Sama obsługa przychodzących wiadomości mogłaby się odbywać w samej klasie Account (powyższy przykład to tylko schemat, ilustrujący jedynie przykładowe rozwiązanie).

Podczas iteracji trzeba by też sprawdzić, czy któryś z obecnych właśnie sie nie wylogował i jakoś się przed tym zabezpieczyć.

Pozdrawiam.

0

Daron widzę, że się wysiliłeś, ale musze się ciebie coś zapytać bo ja nie dawno zaczełem naukę c#.
Czego ja muszę uzyc, aby server(consola) przyjal tekst od jakiegokolwiek klienta, np id 3(przykladowo mowie ID). I żeby ta consola rozesłala do wszystkich to wiadomość... na razie mi tylko na tym zależy.
Dopiero sprawdzalem i zobaczylem ze do servera moze dolaczyc nawet 5 osob, czyli jest chyba nieograniczony.

Zauwazylem, że uzyles translate data, received data ale jak na razie nie rozumiem, 1 to tlumaczy a 2 przyjmuje/odczytuje...

Proszę zmodyfikuj troszkę moj kod, aby server przyjal tekst jakiego kolwiek klienta i ukazal ten tekst dla wszystkich, na razie na nickach mi nie zależy...

Kod:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace granie
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpListener listener = new TcpListener(5000);
            listener.Start();
            Console.WriteLine("Serwer został włączony");
            TcpClient klient = listener.AcceptTcpClient();
            StreamReader streamRead = new StreamReader(klient.GetStream());
            if (klient.Connected)
            {
                Console.WriteLine("Klient połączył sie z serverem");
            }
        }
    }
}
0

@asn2x, z całym szacunkiem do Twojego zapału i Twoich chęci, ale proponuję Ci najpierw złapać podstawy C#, podstawy sieci, a dopiero potem brać się za pisanie takich programów. Myślę, że bardzo dobrze jest zacząć od jakiejś książki i na jej podstawie zaczynać swoją przygodę z C#. Osobiście, choć miałem już spore doświadczenie w C++ kiedy zaczynałem programować w C#, to zaczynałem od tradycyjnego "Hello World" i powoli uczyłem się coraz bardziej zaawansowanych aspektów tego języka. Ale nigdy nie skakałem na głęboką wodę, bo w ten sposób nic nowego się nie nauczysz, jeśli nie będziesz nic rozumiał. Jeśli jednak jest to jakiś projekt zaliczeniowy, to myślę, że marnujesz jedynie swój czas (oczywiście nikt Ci tego nie zabrania).

0

Hmm, na początku dobrze byłoby pomyśleć, jak zbudować "pakiet".
Zajmiemy się najprostszą wersją, tj nasz pakiet będzie wyglądał tak:

struct Pakiet
{
UInt16 MsgLength;
String Message; // String w UTF8
}

Łączna wielkość pakietu to 2 bajty + MsgLength bajtów (+ 1 na każdy jeden polski znak)
Żeby taką wiadomość utworzyć i zamienić na nasz Pakiet (myśląc abstrakcyjnie; nasz Pakiet to po prostu tablica bajtów, zróbmy tak:

byte[] ConvertToBytes(string msg)
{
	System.IO.MemoryStream DataStream = new System.IO.MemoryStream();
	UInt16 MsgLength = (UInt16)Encoding.UTF8.GetByteCount(msg);
	byte[] tmp_data = BitConverter.GetBytes(MsgLength);
	DataStream.Write(tmp_data, 0, 2);
	tmp_data = Encoding.UTF8.GetBytes(msg);
	DataStream.Write(tmp_data, 0, MsgLength);
	return DataStream.GetBuffer(); // albo .ToArray(), o ile pamiętam te dwie metody miały coś spieprzonego w sobie : P
}

void SendDataToSocket(System.Net.Sockets.Socket sock, byte[] data)
{
	String przykladowa_wiadomosc = "wiadomość testowa";
	sock.Send(ConvertToBytes(przykladowa_wiadomosc));
}

void ReadMessageFromBytes(byte[] data)
{
	//Tutaj czytamy wiadomość z otrzymanych bajtów
	System.IO.MemoryStream DataStream = new System.IO.MemoryStream(data);
	byte[] tmp_data = new byte[2]; // Robimy miejsce dla dwóch bajtów dla Uint16
	DataStream.Read(tmp_data, 0, 2);
	UInt16 MsgLength = BitConverter.ToUInt16(tmp_data, 0);
	tmp_data = new byte[MsgLength];
	DataStream.Read(tmp_data, 0, MsgLength);
	String Message = Encoding.UTF8.GetString(tmp_data);
	//Odebraliśmy wiadomość, teraz można z nią robic co sie chce (np. Broadcast(...))
}

Powyższe metody to szkielet Twojego programu. Polecam Ci poczytać tutoriale i obejrzeć kod na stronie, której link podałem w pierwszym poście.

Oczywiście sam pakiet nie może tak wyglądać, wypadałoby umieścić jeszcze nagłówek - jakaś suma kontrolna (ile bajtow ma ogólnie cały pakiet z nagłówkiem), jakieś zabezpieczenia, żeby ktoś nie wysyłał Ci pakietów które nie są zgodne z protokołem itd. Powyższy kod nie ma wielu metod sprawdzania poprawności również w tym sensie, że być może nie caly pakiet doszedł (wtedy możesz czytać bajty... których jeszcze nie ma).

Polecam Ci korzystanie z klasy Socket, a nie TcpClient/TcpListener (moim zdaniem jest większa kontrola nad tym co sie dzieje, ale może jestem w błędzie).

Metoda Receive klasy Socket odbiera bajty które ma dostępne do tablicy, którą wcześniej utworzyłeś.

Poczytaj o tym.

0

gufiak ja bardzo dobrze znam podstawy, pisalem w jezyku podobnym do C, takze zaczynalem od hello world na kursach na 4programers.net czyli tu.... Nie jestem zielony w tym, tylko chce zlapac troche nauki o aplikacjach sieciowych....

1 użytkowników online, w tym zalogowanych: 0, gości: 1