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)
}
}