http://frozzeg.no-ip.info/screens/screen_183_351940399.jpg
Задача сервера: принимать входящие соединения и пакеты (координаты точки, в которой нужно рисовать) от клиентов и разсылать эти координаты всем клиентам, подключенным к серверу.
Задача клиента: при попытке что либо нарисовать, сначала отправляем данные серверу, затем, если отправка прошла успешно - принимать координаты и нарисовать в указанном месте черную точку.
Написание сервера.
Подключаем нужные библиотеки
using System.Net;
using System.Net.Sockets;
using System.Threading;
Инициализация переменных
// Здесь будет хранится статус сервера
bool isServerRunning;
// Здесь будет список наших клиентов
private Hashtable clients;
// Это сокет нашего сервера
Socket listener;
// Порт, на котором будем прослушивать входящие соединения
int port = 1991;
// Точка для прослушки входящих соединений (состоит из адреса и порта)
IPEndPoint Point;
// Список потоков
private List<Thread> threads = new List<Thread>();
ЗНачинаем слушать входящие соединения
private void ServerStart()
{
clients = new Hashtable(30);
isServerRunning = true;
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Определяем конечную точку, IPAddress.Any означает что наш сервер будет принимать входящие соединения с любых адресов
Point = new IPEndPoint(IPAddress.Any, port);
// Связываем сокет с конечной точкой
listener.Bind(Point);
// Начинаем слушать входящие соединения
listener.Listen(10);
SocketAccepter();
}
Обрабатываем входящие соединения
private void SocketAccepter()
{
// Запускаем цикл в отдельном потоке, чтобы приложение не зависло
Thread th = new Thread(delegate()
{
while (isServerRunning)
{
// Создаем новый сокет, по которому мы сможем обращаться клиенту
// Этот цикл остановится, пока какой-нибудь клиент не попытается присоединиться к серверу
Socket client = listener.Accept();
// Теперь, обратившись к объекту client, мы сможем отсылать и принимать пакеты от последнего подключившегося пользователя.
// Добавляем подключенного клиента в список всех клиентов, для дальнейшей массовой рассылки пакетов
clients.Add(client, "");
// Начинаем принимать входящие пакеты
Thread thh = new Thread(delegate()
{
MessageReceiver(client);
});
thh.Start();
}
});
// Приведенный выше цикл пока что не работает, запускаем поток. Теперь цикл работает.
th.Start();
threads.Add(th);
}
Метод приема пакетов
private void MessageReceiver(Socket r_client)
{
// Для каждого нового подключения, будет создан свой поток для приема пакетов
Thread th = new Thread(delegate()
{
while (isServerRunning)
{
try
{
// Сюда будем записывать принятые байты
byte[] bytes = new byte[1024];
// Принимаем
r_client.Receive(bytes);
if (bytes.Length != 0)
{
// Отсылаем принятый пакет от клиента всем клиентам
foreach (Socket s_client in clients.Keys)
{
MessageSender(s_client, bytes);
}
}
}
catch {}
}
});
th.Start();
threads.Add(th);
}
Метод отправки пакетов
private void MessageSender(Socket c_client, byte[] bytes)
{
try
{
// Отправляем пакет
c_client.Send(bytes);
}
catch {}
}
Написание клиента.
Подключаем библиотеки
using System.Net;
using System.Net.Sockets;
using System.Threading;
Инициализация переменных
// Разрешено ли рисовать (т.е. если движение мыши осуществляется при нажатой клавише)
private bool canDraw;
// Статус клиента
private bool client_running;
// Сокет клиента
private Socket client;
// Адрес сервера
private IPAddress ip = IPAddress.Parse("127.0.0.1");
// Порт, по которому будем присоединяться
private int port = 1991;
// Список потоков
private List<Thread> threads = new List<Thread>();
Коннект к серверу
void Connect()
{
try
{
client_running = true;
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(ip, port);
Receiver();
}
catch { }
}
Метод, принимающий данные от сервера
void Receiver()
{
Thread th = new Thread(delegate()
{
while (client_running)
{
try
{
byte[] bytes = new byte[1024];
// Принимает данные от сервера в формате "X|Y"
client.Receive(bytes);
if (bytes.Length != 0)
{
string data = Encoding.UTF8.GetString(bytes);
string[] split_data = data.Split(new Char[] {'|'});
// Передаем отпарсенные значения методу Draw на отрисовку
Draw(Convert.ToInt32(split_data[0]),
Convert.ToInt32(split_data[1]));
}
}
catch {}
}
});
th.Start();
threads.Add(th);
}
Метод для отправки пакетов серверу
void Sender(string msg)
{
try
{
byte[] bytes = new byte[1024];
bytes = Encoding.UTF8.GetBytes(msg);
client.Send(bytes);
}
catch {}
}
Метод рисования
void Draw(int x, int y)
{
try
{
Graphics graphics = CreateGraphics();
graphics.FillEllipse(new SolidBrush(Color.Black), x, y, 5, 5);
}
catch {}
}
Остались пара событий, тут я думаю все итак понятно
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
canDraw = true;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
canDraw = false;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (canDraw)
{
string asd = e.X.ToString() + "|" + e.Y.ToString();
// Посылаем данные серверу (координаты)
Sender(asd);
}
}