Сетевой чат с приватными сообщениями - C#
Формулировка задачи:
Здравствуйте дорогие друзья. Есть вот такой чат, который состоит из сервера и клиента (естественно клиентов может быть много). Сделано все красиво, но нужно его усовершенствовать, а именно нужно сделать так, что бы при входе в чат в checkedListBox выводился список онлайн юзеров. Так же при отправке сообщения можно было выбрать одного или нескольких юзеров которым нужно отправить сообщение. Как это будет проще сделать?
Код клиента (C#):
Код сервера (C++):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;
namespace MyClient
{
public partial class Form1 : Form
{
static private Socket Client;
private IPAddress ip = null;
private int port = 0;
private Thread th;
public Form1()
{
InitializeComponent();
richTextBox1.Enabled = false;
richTextBox2.Enabled = false;
button1.Enabled = false;
try
{
var sr = new StreamReader(@"Client_info/data_info.txt");
string buffer = sr.ReadToEnd();
sr.Close();
string[] connect_info = buffer.Split(':');
ip = IPAddress.Parse(connect_info[0]);
port = int.Parse(connect_info[1]);
label4.ForeColor = Color.Green;
label4.Text = "Настройки: \n IP сервера: " + connect_info[0] + "\n Порт сервера: " + connect_info[1];
}
catch (Exception ex)
{
label4.ForeColor = Color.Red;
label4.Text = "Настройки не найдены";
Form2 form = new Form2();
form.Show();
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void настройкиToolStripMenuItem_Click(object sender, EventArgs e)
{
Form2 form = new MyClient.Form2();
form.Show();
}
void SendMessage(string message)
{
if (message != " " && message != "")
{
byte[] buffer = new byte[1024];
buffer = Encoding.UTF8.GetBytes(message);
Client.Send(buffer);
}
}
void RegOfMessage()
{
byte[] buffer = new byte[1224];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = 0;
}
for (;;)
{
try
{
Client.Receive(buffer);
string messege = Encoding.UTF8.GetString(buffer);
int count = messege.IndexOf(";;;5");
if (count == -1)
{
continue;
}
string Cleaner_Message = "";
for (int i = 0; i < count; i++)
{
Cleaner_Message += messege[i];
}
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = 0;
}
this.Invoke((MethodInvoker)delegate ()
{
richTextBox1.AppendText(Cleaner_Message);
});
}
catch (Exception ex) { }
}
}
private void button2_Click(object sender, EventArgs e)
{
if (textBox1.Text != " " && textBox1.Text != "")
{
button1.Enabled = true;
richTextBox2.Enabled = true;
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (ip != null)
{
Client.Connect(ip, port);
th = new Thread(delegate () { RegOfMessage(); });
th.Start();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
SendMessage("\n" + textBox1.Text + ":" + richTextBox2.Text + ";;;5");
richTextBox2.Clear();
}
private void выходToolStripMenuItem_Click(object sender, EventArgs e)
{
if (th != null) th.Abort();
Application.Exit();
}
private void авторToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Created by N7 \n In 2015 year");
}
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace Client
{
public partial class ChatForm : Form
{
private delegate void ChatEvent(string content,string clr);
private ChatEvent _addMessage;
private Socket _serverSocket;
private Thread listenThread;
private string _host = "127.0.0.1";
private int _port = 2222;
public ChatForm()
{
InitializeComponent();
_addMessage = new ChatEvent(AddMessage);
userMenu = new ContextMenuStrip();
ToolStripMenuItem PrivateMessageItem = new ToolStripMenuItem();
PrivateMessageItem.Text = "Личное сообщение";
PrivateMessageItem.Click += delegate
{
if (userList.SelectedItems.Count > 0)
{
messageData.Text = $""{userList.SelectedItem} ";
}
};
userMenu.Items.Add(PrivateMessageItem);
ToolStripMenuItem SendFileItem = new ToolStripMenuItem()
{
Text = "Отправить файл"
};
SendFileItem.Click += delegate
{
if (userList.SelectedItems.Count == 0)
{
return;
}
OpenFileDialog ofp = new OpenFileDialog();
ofp.ShowDialog();
if (!File.Exists(ofp.FileName))
{
MessageBox.Show($"Файл {ofp.FileName} не найден!");
return;
}
FileInfo fi = new FileInfo(ofp.FileName);
byte[] buffer = File.ReadAllBytes(ofp.FileName);
Send($"#sendfileto|{userList.SelectedItem}|{buffer.Length}|{fi.Name}");//g
Send(buffer);
};
userMenu.Items.Add(SendFileItem);
userList.ContextMenuStrip = userMenu;
}
private void AddMessage(string Content,string Color = "Black")
{
if(InvokeRequired)
{
Invoke(_addMessage,Content,Color);
return;
}
chatBox.SelectionStart = chatBox.TextLength;
chatBox.SelectionLength = Content.Length;
chatBox.SelectionColor = getColor(Color);
chatBox.AppendText(Content + Environment.NewLine);
}
private Color getColor(string text)
{
//govno
if (Color.Red.Name.Contains(text))
return Color.Red;
return Color.Black;
}
private void ChatForm_Load(object sender, EventArgs e)
{
IPAddress temp = IPAddress.Parse(_host);
_serverSocket = new Socket(temp.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
_serverSocket.Connect(new IPEndPoint(temp, _port));
if (_serverSocket.Connected)
{
enterChat.Enabled = true;
nicknameData.Enabled = true;
AddMessage("Связь с сервером установлена.");
listenThread = new Thread(listner);
listenThread.IsBackground = true;
listenThread.Start();
}
else
AddMessage("Связь с сервером не установлена.");
}
public void Send(byte[] buffer)
{
try
{
_serverSocket.Send(buffer);
}
catch { }
}
public void Send(string Buffer)
{
try
{
_serverSocket.Send(Encoding.Unicode.GetBytes(Buffer));
}
catch { }
}
public void handleCommand(string cmd)
{
string[] commands = cmd.Split('#');
int countCommands = commands.Length;
for (int i = 0; i < countCommands; i++)
{
try
{
string currentCommand = commands[i];
if (string.IsNullOrEmpty(currentCommand))
continue;
if (currentCommand.Contains("setnamesuccess"))
{
//Из-за того что программа пыталась получить доступ к контролам из другого потока вылетал эксепщен и поля не разблокировались
Invoke((MethodInvoker)delegate
{
AddMessage($"Добро пожаловать, {nicknameData.Text}");
nameData.Text = nicknameData.Text;
chatBox.Enabled = true;
messageData.Enabled = true;
userList.Enabled = true;
nicknameData.Enabled = false;
enterChat.Enabled = false;
});
continue;
}
if(currentCommand.Contains("setnamefailed"))
{
AddMessage("Неверный ник!");
continue;
}
if(currentCommand.Contains("msg"))
{
string[] Arguments = currentCommand.Split('|');
AddMessage(Arguments[1], Arguments[2]);
continue;
}
if(currentCommand.Contains("userlist"))
{
string[] Users = currentCommand.Split('|')[1].Split(',');
int countUsers = Users.Length;
userList.Invoke((MethodInvoker)delegate { userList.Items.Clear(); });
for(int j = 0;j < countUsers;j++)
{
userList.Invoke((MethodInvoker)delegate { userList.Items.Add(Users[j]) ; });
}
continue;
}
if(currentCommand.Contains("gfile"))
{
string[] Arguments = currentCommand.Split('|');
string fileName = Arguments[1];
string FromName = Arguments[2];
string FileSize = Arguments[3];
string idFile = Arguments[4];
DialogResult Result = MessageBox.Show($"Вы хотите принять файл {fileName} размером {FileSize} от {FromName}","Файл",MessageBoxButtons.YesNo);
if (Result == DialogResult.Yes)
{
Thread.Sleep(1000);
Send("#yy|"+idFile);
byte[] fileBuffer = new byte[int.Parse(FileSize)];
_serverSocket.Receive(fileBuffer);
File.WriteAllBytes(fileName, fileBuffer);
MessageBox.Show($"Файл {fileName} принят.");
}
else
Send("nn");
continue;
}
}
catch (Exception exp) { Console.WriteLine("Error with handleCommand: " + exp.Message); }
}
}
public void listner()
{
try
{
while (_serverSocket.Connected)
{
byte[] buffer = new byte[2048];
int bytesReceive = _serverSocket.Receive(buffer);
handleCommand(Encoding.Unicode.GetString(buffer, 0, bytesReceive));
}
}
catch
{
MessageBox.Show("Связь с сервером прервана");
Application.Exit();
}
}
private void enterChat_Click(object sender, EventArgs e)
{
string nickName = nicknameData.Text;
if (string.IsNullOrEmpty(nickName))
return;
Send($"#setname|{nickName}");
}
private void ChatForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_serverSocket.Connected)
Send("#endsession");
}
private void messageData_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyData == Keys.Enter)
{
string msgData = messageData.Text;
if (string.IsNullOrEmpty(msgData))
return;
if(msgData[0] == '"')
{
string temp = msgData.Split(' ')[0];
string content = msgData.Substring(temp.Length+1);
temp = temp.Replace(""", string.Empty);
Send($"#private|{temp}|{content}");
}
else
Send($"#message|{msgData}");
messageData.Text = string.Empty;
}
}
}
}Решение задачи: «Сетевой чат с приватными сообщениями»
textual
Листинг программы
#pragma comment(lib,"Ws2_32.lib")
#include <WinSock2.h>
#include <iostream>
#include <WS2tcpip.h>
SOCKET Connect;
SOCKET* Connections;
SOCKET Listen;
int ClientCount = 0;
void SendMessageToClient(int ID)
{
char* buffer = new char[1024];
for (;; Sleep(75))
{
memset(buffer, 0, sizeof(buffer));
if (recv(Connections[ID], buffer, 1024, NULL))
{
printf(buffer);
printf("/n");
for (int i = 0; i <= ClientCount; i++)
{
send(Connections[i], buffer, strlen(buffer), NULL);
}
}
}
delete buffer;
}
int main()
{
setlocale(LC_ALL, "russian");
WSAData data;
WORD version = MAKEWORD(2, 2);
int res = WSAStartup(version, &data);
if (res != 0)
{
return 0;
}
struct addrinfo hints;
struct addrinfo * result;
Connections = (SOCKET*)calloc(64, sizeof(SOCKET));
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
getaddrinfo(NULL, "7770", &hints, &result);
Listen = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
bind(Listen, result->ai_addr, result->ai_addrlen);
listen(Listen, SOMAXCONN);
freeaddrinfo(result);
printf("Server connect...");
char m_connetc[] = "Connect...;;;5";
for (;; Sleep(75))
{
if (Connect = accept(Listen, NULL, NULL))
{
printf("Client connect.../n");
Connections[ClientCount] = Connect;
send(Connections[ClientCount], m_connetc, strlen(m_connetc), NULL);
ClientCount++;
CreateThread(NULL, NULL, (PTHREAD_START_ROUTINE)SendMessageToClient, (LPVOID)(ClientCount - 1), NULL, NULL);
}
}
return 1;
}