I wanted to make a chat client server, very simple, but at the same time very safe, using AES-256bit. I have thought so, tell me if I'm wrong, of course.
The various client enter in a "secure" textbox the passwords (which must be the same everywhere) and in the sending functions (of the client program), clients encrypt messages that I put in another ordinary textbox, using the password and send them to the server; the receiving function always decrypts always using the same key. The server should instead do nothing at the encryption level.
I tried, but I do not know if it doesn't work because of at the code level.
Here's how I modified both the sending and receiving functions on the client: send function
// send the message to the server
private void SendMessage()
{
if (txtMessage.Lines.Length >= 1)
{
byte[] passwordBytes = GetPasswordBytes();
encrypted_message = AES.Encrypt(txtMessage.Text, passwordBytes);
swSender.WriteLine(encrypted_message);
swSender.Flush();
txtMessage.Lines = null;
}
txtMessage.Text = "";
}
receiving function:
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Connessione avvenuta con successo!" });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = "Non connesso: ";
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length - 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
// While we are successfully connected, read incoming lines from the server
while (Connected == true)
{
try
{
// Show the messages decrypted in the log TextBox
this.Invoke(new UpdateLogCallback(this.MessageUpdateLog), new object[] { srReceiver.ReadLine() });
}
catch
{
try
{
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
catch { }
}
}
}
// This method is called from a different thread in order to update the log TextBox
private void UpdateLog(string strMessage)
{
txtLog.AppendText(strMessage + "\r\n");
}
//Decrypt the messages incoming from the other client
private void MessageUpdateLog(string strMessage_de)
{
byte[] passwordBytes = GetPasswordBytes();
strMessage_de = AES.Decrypt(strMessage_de, passwordBytes);
// Append text also scrolls the TextBox to the bottom each time
txtLog.AppendText(strMessage_de + "\r\n");
}
not to make the job hard, I thought of exchange encryption passwords (keys) via voice, since it would be a chat room for personal use.
Related
I've got the client/server working, the client is sending data to the server with no issues, and right now I just have a RichTextBox displaying the data received from the client.
What I would like to do is have the server display the data received in the RichTextBox, and then SendKeys the message to the active window (the server will be minimized to the system tray while this is happening).
CLIENT PORTION:
using System.Net;
using System.Net.Sockets;
private TcpClient client = new TcpClient();
private IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("MyIP"), 8888);
public Console()
{
InitializeComponent();
client.Connect(serverEndPoint);
}
private void SendMessage(string msg)
{
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
///...
private void button1_Click(object sender, EventArgs e)
{
SendMessage("T");
}
Now, all of that seems fine to me, as my server app is receiving the message just fine. My problem is on the server side. I can't seem to get the SendKeys function to work properly, so I've commented it out of my code snippet:
SERVER PORTION:
using System.Net;
using System.Net.Sockets;
using System.Threading;
private TcpListener tcpListener;
private Thread listenThread;
private int connectedClients = 0;
private delegate void WriteMessageDelegate(string msg);
public Form1()
{
InitializeComponent();
Server();
}
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
connectedClients++;
lblNumberOfConnections.Text = connectedClients.ToString();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
if (bytesRead == 0)
{
connectedClients--;
lblNumberOfConnections.Text = connectedClients.ToString();
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
//Write message in RichTextBox and send keystrokes to active window
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
// SendKeys.Send(msg);
}
tcpClient.Close();
}
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
}
As I said, it displays the data in the textbox just fine, but what I'd like to do as well (and the main purpose of this app) is to take the message received from the client, and add it to a SendKeys (or similar), and simulate those key presses in the active window. I just can't seem to figure out how to do that though...
Also, since I used SendMessage in my client app, and some of the keypresses I need to send to the active window contain modifiers, I just sent them as a text message to my server (ie. for the command CTRL-T, I literally sent the text "CTRL-T" to my server app), I was hoping I could do something along the lines of this:
If message is received as a single keystroke, just use SendKeys (ie. SendKeys.Send("T");)
If message is received as a keystroke with a modifier (ie. CTRL-T) change it to proper SendKeys modifier (ie. SendKeys.Send("{^T}");)
I don't have a problem assigning the events for commands with modifiers manually, since there is only going to be two commands being received that use modifiers, but I'm not sure how to implement that part either.
I would like my server to send the string received from my client (which I believe is msg) and send it to the active window as a keypress. I would like to add an "IF" statement to the code so that if the server receives a certain message (the commands with modifiers; which are all known commands, so I could program which commands to listen for), it sends a specified keypress(depending on which command was received) to the active window.
UPDATE:
I've managed to figure out how to use SendKeys to send the data from the client to the active window on the server machine. It was my original placement of the SendKeys command that needed changing. I've updated it as follows:
//Write message in RichTextBox
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
}
tcpClient.Close();
}
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
// SEND KEYSTROKES TO ACTIVE WINDOW
SendKeys.Send(msg);
}
Now my problem is back to me being inexperienced with C#.
I'm not sure of the proper way to implement the IF statement I need to catch the string before I send it to the active window. I need to use an IF statement to catch the string first, because some of the messages coming from the server aren't formatted as proper keystrokes.
Basically, what I'd like to do is have anything that is just a single character slip by my IF statement, and look for two particular messages.
The two messages I need to intercept are "CTRL-T" and "CTRL-H".
I don't know the proper formatting, since this is my first C# app, and I'm learning as I go, but my idea is to tell the program as follows:
If the message contained in the string is "CTRL-T" then SendKeys.Send("{^T}");
If the message contained in the string is "CTRL-H" then SendKeys.Send("{^H}");
If it is anything else then SendKeys.Send(msg);
Does that sound like the proper way to accomplish what I've explained here?
EDIT: I've attempted to figure out how to format my IF statement, but it's obviously wrong:
// SEND KEYSTROKES TO ACTIVE WINDOW
if (msg.Equals("CTRL-T"))
{
SendKeys.Send("{^T}");
}
else if (msg.Equals("CTRL-H"))
{
SendKeys.Send("{^H}");
}
else
{
SendKeys.Send(msg);
}
I tested the first IF statement by replacing "{^T}" with "TEST" and it sends the word TEST to notepad with no issues, but when I put in "{^T}", as soon as I hit the button to send that command, my server crashes.
The same thing happens for trying to send "{^H}"
Anyone have an idea what I'm doing wrong here?
I guess I'll answer my own question, since I've got the basic functionality that I was looking for now.
Basically, I wanted to accept a message from a client app, and display it in a text box on my server app, and then convert that message to simulated keypresses in the active window.
Before sending the keypresses to the window, I had to make sure that only the single digit keypresses were being sent to the active window immediately, and the other two known commands that needed modifiers attached to them were caught before being sent, and modified so they would act as modified keypresses, and not sent as a chunk of text (ie. "CTRL-T") instead of the actual "CTRL" button+T button
//Write message in RichTextBox
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
}
tcpClient.Close();
}
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
// SEND KEYSTROKES TO ACTIVE WINDOW
if (msg.Equals("CTRL-T"))
{
SendKeys.Send("^T");
}
else if (msg.Equals("CTRL-H"))
{
SendKeys.Send("^H");
}
else
{
SendKeys.Send(msg);
}
Overview of Problem:
I need to connect to an IRC Server. Once connected, the program will send a message to the channel, and a response will occur over multiple lines back. I need to read these lines and store in a variable for later use. A special character at the end of the message (]) will define the end of the message over multiple lines. Once we have received this character, the IRC session should disconnect and processing should continue.
Situation:
I am using the Smartirc4net library. Calling irc.Disconnect() takes about 40 seconds to disconnect the session. Once we've received the ] character, the session should be disconnected, Listen() should not be blocking, and the rest of the program should continue to run.
Research:
I have found this: smartirc4net listens forever, can't exit thread, and I think it might be the same issue, however, I am unsure of what I need to do to resolve the problem.
Code:
public class IrcCommunicator
{
public IrcClient irc = new IrcClient();
string data;
public string Data { get { return data; } }
// this method we will use to analyse queries (also known as private messages)
public void OnQueryMessage(object sender, IrcEventArgs e)
{
data += e.Data.Message;
if (e.Data.Message.Contains("]"))
{
irc.Disconnect(); //THIS TAKES 40 SECONDS!!!
}
}
public void RunCommand()
{
irc.OnQueryMessage += new IrcEventHandler(OnQueryMessage);
string[] serverlist;
serverlist = new string[] { "127.0.0.1" };
int port = 6667;
string channel = "#test";
try
{
irc.Connect(serverlist, port);
}
catch (ConnectionException e)
{
// something went wrong, the reason will be shown
System.Console.WriteLine("couldn't connect! Reason: " + e.Message);
}
try
{
// here we logon and register our nickname and so on
irc.Login("test", "test");
// join the channel
irc.RfcJoin(channel);
irc.SendMessage(SendType.Message, "test", "!query");
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
irc.Listen();
// when Listen() returns our IRC session is over, to be sure we call
// disconnect manually
irc.Disconnect();
}
catch (Exception e)
{
// this should not happen by just in case we handle it nicely
System.Console.WriteLine("Error occurred! Message: " + e.Message);
System.Console.WriteLine("Exception: " + e.StackTrace);
}
}
}
IrcBot bot = new IrcBot();
bot.RunCommand();
ViewBag.IRC = bot.Data;
As you can see, once this
Thank you for your time to look at this code and read my problem description. If you have any thoughts, or other suggestions, please let me know.
Mike
I was able to successfully disconnect straight away by calling RfcQuit() within OnQueryMessage(), before irc.Disconnect();
I am new to socket programming (especially to asyncsockets).
I used this tutorial http://www.codeproject.com/Articles/22918/How-To-Use-the-SocketAsyncEventArgs-Class to get an AsynSocketserver (my client uses synchronous sockets)
Basically it works. The client can connect to the server, send some data and get it echoed back.
I have this code (in a SocketListener class) to receive the data (without echo):
private void ProcessReceive(SocketAsyncEventArgs e) {
//check if remote host closed the connection
if (e.BytesTransferred > 0) {
if (e.SocketError == SocketError.Success) {
Token token = e.UserToken as Token;
token.SetData(e);
Socket s = token.Connection;
if (s.Available == 0) {
token.ProcessData(e);
}
bool IOPending = s.ReceiveAsync(e);
if (!IOPending) {
ProcessReceive(e);
}
//echo back
/* if (s.Available == 0) {
//set return buffer
token.ProcessData(e);
if (!s.SendAsync(e)) {
this.ProcessSend(e);
}
} else if (!s.ReceiveAsync(e)) {
this.ProcessReceive(e);
}*/
} else {
this.ProcessError(e);
}
} else {
this.CloseClientSocket(e);
}
}
private void ProcessSend(SocketAsyncEventArgs e) {
if(e.SocketError == SocketError.Success){
Token token = e.UserToken as Token;
if(!token.Connection.ReceiveAsync(e)){
this.ProcessReceive(e);
}
} else {
this.ProcessError(e);
}
}
Now I want that the client can connect to the server (maybe send some data to server, but it should not be necessary that the client sends at first some data to the server, it only needs to connect to the server) and that the client can receive some data from the server.
Problem: I have no idea where or how to use the socketEventArgs.senAsync()-method without receiving data before.
Currently I am using a send()-method in the Token-Class, that creates a new AsyncEventArgs object and uses the (in the token) stored connection to send data:
public void send() {
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.UserToken = this;
args.SetBuffer(sendBuffer, 0, sendBuffer.Length);
connection.SendAsync(args);
}
it works, but this seems to be the wrong approach.
So, how do I send data to a client with an open connection without receiving data from the client first?
To me, the only thing "wrong" in there is that you aren't checking the return value of SendAsync (it could have returned synchronously, especially in the case of failure) - and you don't have a Completed event subscription, so when synchronous or asynchronous, you won't be able to detect failure. Also, it is probably possible (and certainly desirable) to re-use the SocketAsyncEventArgs instance, rather than new-ing one for every send.
But fundamentally: fine. You can send at any point, really.
I have just started to learn C++ and Java. For my first project, I made a C++ TCP socket server. Unfortunately, it don't work as I expected.
How it works:
If I start my Java Android client, my C++ server instantly detects a new connection.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.intrologin_layout);
client = new TCPClient("10.0.2.2", 50120);
try {
new Thread() {
public void run() {
try {
client.startClient();
}
catch(Exception e) {
e.printStackTrace();
}
}
}.start();
}
catch(Exception e) {
e.printStackTrace();
}
}
Sending bytes also works through the Java Android client:
output = new DataOutputStream(connectionSocket.getOutputStream());
output.write(Packet);
output.flush();
My C++ server returns automaticly received packets in the console, which works pretty well,
but then I try to send a reply back, the recv worked on my C++ client but here is the main problem, it don't on my Java client until I close the server process or the socket.
C++ serverside:
pd->SendPacket("BYE\0", 4);
...
void Desc::SendPacket(const char* c_cpBuffer, int Length)
{
int BytesSended = send(m_Socket, c_cpBuffer, Length, 0);
if (BytesSended <= 0)
{
printf("Packet send failed with error: %d\n", WSAGetLastError());
}
}
Java Android clientside:
public void startClient() throws Exception
{
connectionSocket = new Socket(ip, port);
input = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
output = new DataOutputStream(connectionSocket.getOutputStream());
messageReceiver = new Thread() {
public void run()
{
while(connectionSocket.isConnected()) {
try {
String receivedMessage = input.readLine();
input.toString();
if(receivedMessage != null) {
Log.e("ERROR", "ERROR");
Log.d("Received Message: ", receivedMessage);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
messageReceiver.start();
}
I stuck in this problem since weeks, thank you.
You have input.readLine() and that would not return unless a line feed is detected. If your server sends messages that are terminated by line feed, your java client should pick that up.
The following is code printing what is received from server. Use BufferedInputStream rather than BufferedReader. Haven't tested the code below but it will read up to 10 bytes from server each time. Because it is buffered, I am not sure how "real time" it is. For example, server sends 3 characters then sleep for 5 seconds and sends 7 chars. Whether client will receive 3 chars immediately and print that followed by 7 chars after 5 seconds or client will wait and receive 10 chars after 5 seconds and print all 10 at once, you need to test that.
BufferedInputStream input = new BufferedInputSream(socket.getInputStream());
byte[] buffer = new byte[10]; // 10 bytes buffer
int bytesRead = 0;
while( (bytesRead=input.read(buffer)) !=-1 ) { // read up to 10 bytes
String str = new String(buffer,0,bytesRead); // convert bytes to String using default encoding
System.out.println("Data received: " + str);
}
I was stuck at the same problem for Month, even redo whole project differently still didn't helped me, and the problem is so simple. in.readline() function expects end of line to continue, so you should append it to your buffer.
pd->SendPacket("BYE\0\n", 4);
Hope it helped, like it helped me.
Good afternoon all!
The goal of the project:
Build a notification program with client, console, and server executable. Only selected users should get the notification.
The problem:
Sometimes the code works great, and everything works (20% of runs). The rest of the time, it will mess up the order the data is being sent in.
The code:
Server (console = TCPclient):
private void Connect()
{
string username = ReadFromConsole();
if (IsUserAllowed(username)) // Receive username
SendToConsole(bool.TrueString); // Send confirmation
else
{
SendToConsole(bool.FalseString); // Send denial
console.Close();
return;
}
string messageID = ReadFromConsole(); // Receive MessageID
string recipientCount = ReadFromConsole();
int numOfRecipients = int.Parse(recipientCount); // Receive and parse number of recipients
List<string> recipients = new List<string>();
for (int i = 0; i < numOfRecipients; i++)
{
string recipient = ReadFromConsole();
recipients.Add(recipient); // Receive recipient, add to list (required for Message)
}
string department = ReadFromConsole(); // Receive department string
string visibleTime = ReadFromConsole(); // Receive visibility timespan
string expiration = ReadFromConsole(); // Receive expiration datetime
StoreRTF(messageID); // Receive and store RTF file
console.Close(); // Connection is done, close
Message message = new Message(messageID, department, recipients, visibleTime, expiration);
}
Console (server = TCPclient):
private void SendMessage()
{
SendToServer(Environment.UserName);
if (bool.Parse(ReadFromServer()))
{
// User is allowed, continue
string messageID = DateTime.Now.ToUniversalTime().Ticks.ToString();
SendToServer(messageID); // MessageID
string recipientCount = lvRecipients.Items.Count.ToString();
SendToServer(lvRecipients.Items.Count.ToString()); // Amount of recipients
foreach (string item in lvRecipients.Items) // Loop to send each recipient
{
SendToServer(item);
}
string department = TB_Department.Text;
SendToServer(department); // Send department string
string visibleTime = TimeSpan.FromSeconds(SLIDER_VisibleTime.Value).Ticks.ToString();
SendToServer(visibleTime); // Send message visibility time
string expiration = DateTime.Now.ToUniversalTime().AddMinutes(2).ToString();
SendToServer(expiration); //TODO add UI control for this
SendRTFToServer(); // Send RTF file
MessageBox.Show(
"Your designated MessageID is: " + messageID + Environment.NewLine +
"Message upload is succesful.",
"Complete",
MessageBoxButton.OK);
}
else
{
// User is not allowed. Report to user. Disconnect (will be managed by the finally block)
MessageBox.Show("You are not allowed to upload messages to the server.", "Access denied", MessageBoxButton.OK, MessageBoxImage.Stop);
return;
}
}
Send and receive parts (same between console/server/client):
private void SendToServer(string toSend)
{
while (server.GetStream().DataAvailable)
{
// Should wait
}
StreamWriter writer = new StreamWriter(server.GetStream());
writer.WriteLine(toSend);
writer.Flush();
}
private void SendRTFToServer()
{
while (server.GetStream().DataAvailable)
{
// Should wait
}
File.Open(RTFLocation, FileMode.Open, FileAccess.Read).CopyTo(server.GetStream());
server.GetStream().Flush();
server.GetStream().Close();
}
private string ReadFromServer()
{
server.GetStream().Flush();
StreamReader reader = new StreamReader(server.GetStream());
return reader.ReadLine();
}
I have also tried different loops, implementations, switching to byte[]...
After lots of debugging I am getting nowhere. I have checked which information is leaving the console, and that all checks out and is in the right order. However, at the server end it seems to be receiving it in an entirely different order.
Anyone have an idea what is causing this?
I've found how to properly handle this. Code for the relevant parts can be found here:
C# Sockets send/receive problems and questions
Hope this may help someone in the future!