I need some help. I've been searching the internet for days, but i dont get it together. I have a code for a TCP Server. It runs just fine, the only thing what is lacking is the possibility to send a message to one specific client (like a Pivat Message).
How do i put Multiple Clients into this code??
I'm a total Beginner, so I hope someone can help me.==================================================
using System;using System.Collections.Generic;using System.Collections;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Net;using System.Net.Sockets;
namespace Server{ //The commands for interaction between the server and the client enum Command { Login, //Log into the server Logout, //Logout of the server Message, //Send a text message to all the chat clients List, //Get a list of users in the chat room from the server Null //No command }
public partial class SGSserverForm : Form { //The ClientInfo structure holds the required information about every //client connected to the server struct ClientInfo { public Socket socket; //Socket of the client public string strName; //Name by which the user logged into the chat room }
//The collection of all clients logged into the room (an array of type ClientInfo) ArrayList clientList;
//The main socket on which the server listens to the clients Socket serverSocket;
byte[] byteData = new byte[1024];
public SGSserverForm() { clientList = new ArrayList(); InitializeComponent(); }
private void Form1_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false; try { //We are using TCP sockets serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Assign the any IP of the machine and listen on port number 1000 IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 1000);
//Bind and listen on the given address serverSocket.Bind(ipEndPoint); serverSocket.Listen(4);
//Accept the incoming clients serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); ; } catch (Exception ex) { MessageBox.Show(ex.Message, "TCPServer", } }
private void OnAccept(IAsyncResult ar) { try { Socket clientSocket = serverSocket.EndAccept(ar); //Start listening for more clients serverSocket.BeginAccept(new AsyncCallback(OnAccept), null); //Once the client connects then start receiving the commands from her clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } catch (Exception ex) { MessageBox.Show(ex.Message, "TCPServer", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void OnReceive(IAsyncResult ar) { try { Socket clientSocket = (Socket)ar.AsyncState; clientSocket.EndReceive(ar); //Transform the array of bytes received from the user into an //intelligent form of object Data Data msgReceived = new Data(byteData);
//We will send this object in response the users request Data msgToSend = new Data();
byte [] message; //If the message is to login, logout, or simple text message //then when send to others the type of the message remains the same msgToSend.cmdCommand = msgReceived.cmdCommand; msgToSend.strName = msgReceived.strName; switch (msgReceived.cmdCommand) { case Command.Login: //When a user logs in to the server then we add her to our //list of clients
ClientInfo clientInfo = new ClientInfo(); clientInfo.socket = clientSocket; clientInfo.strName = msgReceived.strName; button1.Text = clientSocket.GetType().ToString(); clientList.Add(clientInfo); //Set the text of the message that we will broadcast to all users msgToSend.strMessage = "<<<" + msgReceived.strName + " has joined the room>>>"; break;
case Command.Logout: //When a user wants to log out of the server then we search for her //in the list of clients and close the corresponding connection
int nIndex = 0; foreach (ClientInfo client in clientList) { if (client.socket == clientSocket) { clientList.RemoveAt(nIndex); break; } ++nIndex; } clientSocket.Close(); msgToSend.strMessage = "<<<" + msgReceived.strName + " has left the room>>>"; break;
case Command.Message:
//Set the text of the message that we will broadcast to all users msgToSend.strMessage = msgReceived.strName + ": " + msgReceived.strMessage; break;
case Command.List:
//Send the names of all users in the chat room to the new user msgToSend.cmdCommand = Command.List; msgToSend.strName = null; msgToSend.strMessage = null;
//Collect the names of the user in the chat room foreach (ClientInfo client in clientList) { //To keep things simple we use asterisk as the marker to separate the user names msgToSend.strMessage += client.strName + "*"; }
message = msgToSend.ToByte();
//Send the name of the users in the chat room clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientSocket); break; }
if (msgToSend.cmdCommand != Command.List) //List messages are not broadcasted { message = msgToSend.ToByte();
foreach (ClientInfo clientInfo in clientList) { if (clientInfo.socket != clientSocket || msgToSend.cmdCommand != Command.Login) { //Send the message to all users clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(OnSend), clientInfo.socket); } txtLog.Text += msgReceived.strMessage + "\r\n"; }
//txtLog.Text += msgToSend.strMessage + "\r\n"; //txtLog.Text = msgToSend.strMessage; }
//If the user is logging out then we need not listen from her if (msgReceived.cmdCommand != Command.Logout) { //Start listening to the message send by the user clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), clientSocket); } } catch (Exception ex) { MessageBox.Show(ex.Message, "TCPServer", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
public void OnSend(IAsyncResult ar) { try { Socket client = (Socket)ar.AsyncState; client.EndSend(ar); } catch (Exception ex) { MessageBox.Show(ex.Message, "TCPServer", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void button1_Click(object sender, EventArgs e) { // Sendbutton } }
//The data structure by which the server and the client interact with //each other class Data { //Default constructor public Data() { this.cmdCommand = Command.Null; this.strMessage = null; this.strName = null; }
//Converts the bytes into an object of type Data public Data(byte[] data) { //The first four bytes are for the Command this.cmdCommand = (Command)BitConverter.ToInt32(data, 0);
//The next four store the length of the name int nameLen = BitConverter.ToInt32(data, 4);
//The next four store the length of the message int msgLen = BitConverter.ToInt32(data, 8);
//This check makes sure that strName has been passed in the array of bytes if (nameLen > 0) this.strName = Encoding.UTF8.GetString(data, 12, nameLen); else this.strName = null;
//This checks for a null message field if (msgLen > 0) this.strMessage = Encoding.UTF8.GetString(data, 12 + nameLen, msgLen); else this.strMessage = null; }
//Converts the Data structure into an array of bytes public byte[] ToByte() { List<byte> result = new List<byte>();
//First four are for the Command result.AddRange(BitConverter.GetBytes((int)cmdCommand));
//Add the length of the name if (strName != null) result.AddRange(BitConverter.GetBytes(strName.Length)); else result.AddRange(BitConverter.GetBytes(0));
//Length of the message if (strMessage != null) result.AddRange(BitConverter.GetBytes(strMessage.Length)); else result.AddRange(BitConverter.GetBytes(0));
//Add the name if (strName != null) result.AddRange(Encoding.UTF8.GetBytes(strName));
//And, lastly we add the message text to our array of bytes if (strMessage != null) result.AddRange(Encoding.UTF8.GetBytes(strMessage));
return result.ToArray(); }
public string strName; //Name by which the client logs into the room public string strMessage; //Message text public Command cmdCommand; //Command type (login, logout, send message, etcetera) } }