i would like to send message from my web page (client) to a pc
Problem comes in when I try to send data. It complains about this line: m_socWorker.Send(byData); Error Message is Object reference not set to an instance of an object.
here is my code
// Counts the pings
private int pingsSent;
// Can be used to notify when the operation completes
AutoResetEvent resetEvent = new AutoResetEvent(false);
public static Socket m_socWorker;
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropDownList2.SelectedIndex != null)
{
// Reset the number of pings
pingsSent = 0;
// Clear the textbox of any previous content
TextBox2.Dispose();
TextBox2.Text += "Pinging " + DropDownList1.SelectedValue + " with 32 bytes of data:\r\n\r\n";
// Send the ping
Thread thd = new Thread(new ThreadStart(SendPing));
thd.Start();
//SendPing();
try
{
UdpClient udpclient = new UdpClient();
IPAddress remotipadd = IPAddress.Parse(DropDownList1.SelectedValue);
udpclient.Connect(remotipadd,10001);
byte[] data = new byte[1024];
IPEndPoint senderip = new IPEndPoint(remotipadd, Convert.ToInt32(DropDownList2.SelectedValue));
udpclient.Connect(senderip);
TextBox2.Text += "Connect";
// listbox1.Items.Add("connected");
}
catch (SocketException s)
{
MessageBox.Show(s.Message);
}
}
}
private void SendPing()
{
System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
// Create an event handler for ping complete
pingSender.PingCompleted += new PingCompletedEventHandler(pingSender_Complete);
// Create a buffer of 32 bytes of data to be transmitted.
byte[] packetData = Encoding.ASCII.GetBytes("................................");
// Jump though 50 routing nodes tops, and don't fragment the packet
PingOptions packetOptions = new PingOptions(50, true);
// Send the ping asynchronously
pingSender.SendAsync(DropDownList1.SelectedValue, 5000, packetData, packetOptions, resetEvent);
}
private void pingSender_Complete(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
TextBox2.Text += "Ping was canceled...\r\n";
// The main thread can resume
((AutoResetEvent)e.UserState).Set();
}
else if (e.Error != null)
{
TextBox2.Text += "An error occured: " + e.Error + "\r\n";
// The main thread can resume
((AutoResetEvent)e.UserState).Set();
}
else
{
PingReply pingResponse = e.Reply;
// Call the method that displays the ping results, and pass the information with it
ShowPingResults(pingResponse);
}
}
public void ShowPingResults(PingReply pingResponse)
{
if (pingResponse == null)
{
// We got no response
TextBox2.Text += "There was no response.\r\n\r\n";
return;
}
else if (pingResponse.Status == IPStatus.Success)
{
// We got a response, let's see the statistics
TextBox2.Text += "Reply from " + pingResponse.Address.ToString() + ": bytes=" + pingResponse.Buffer.Length + " time=" + pingResponse.RoundtripTime + " TTL=" + pingResponse.Options.Ttl + "\r\n";
}
else
{
// The packet didn't get back as expected, explain why
TextBox2.Text += "Ping was unsuccessful: " + pingResponse.Status + "\r\n\r\n";
}
// Increase the counter so that we can keep track of the pings sent
pingsSent++;
// Send 4 pings
if (pingsSent < 4)
{
SendPing();
}
}
protected void Button2_Click(object sender, EventArgs e)
{
try
{
Object objData = TextBox2.Text;
byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString());
//Session["m_socWorker"] = m_socWorker;
//m_socWorker = (Socket) Session["m_socWorker"];
m_socWorker.Send(byData);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
Related
I'm developing a sample program to connect multiple device using backgroundworker. Each device connected will be add to the list as new object. After finished connecting all the devices, i wanted to add an event handler for each connected devices. The problem that i'm facing now is the event handler doesn't firing at all. Below are the sample codes.
The Connect click button event :
private void btnConnect_Click(object sender, EventArgs e)
{
using (BackgroundWorker m_oWorker = new BackgroundWorker())
{
m_oWorker.DoWork += delegate (object s, DoWorkEventArgs args)
{
int iIpStart = 0;
int iIpEnd = 0;
string strIp1 = string.Empty;
string strIp2 = string.Empty;
list.Clear();
string[] sIP1 = txtIpStart.Text.Trim().ToString().Split('.');
string[] sIP2 = txtIpEnd.Text.Trim().ToString().Split('.');
iIpStart = Convert.ToInt32(sIP1[3]);
iIpEnd = Convert.ToInt32(sIP2[3]);
strIp1 = sIP1[0] + "." + sIP1[1] + "." + sIP1[2] + ".";
strIp2 = sIP2[0] + "." + sIP2[1] + "." + sIP2[2] + ".";
Ping ping = new Ping();
PingReply reply = null;
int iIncre = 0;
int iVal = (100 / (iIpEnd - iIpStart));
for (int i = iIpStart; i <= iIpEnd; i++)
{
Thread.Sleep(100);
string strIpconnect = strIp1 + i.ToString();
Console.Write("ip address : " + strIpconnect + ", status: ");
reply = ping.Send(strIpconnect);
if (reply.Status.ToString() == "Success")
{
if (ConnectDevice(strIpconnect))
{
strLastDevice = strIpconnect + " Connected";
isconnected = true;
}
else
{
isconnected = false;
}
}
else
{
isconnected = false;
}
m_oWorker.ReportProgress(iIncre);
iIncre = iIncre + iVal;
}
m_oWorker.ReportProgress(100);
};
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
m_oWorker.RunWorkerAsync();
}
}
ConnectDevice function method. Connected device will be added to the list :
protected bool ConnectDevice(string sIP)
{
try
{
NewSDK sdk = new NewSDK();
if (sdk.Connect() == true)
{
list.Add(new objSDK { sdk = sdk, ipaddress = sIP });
return true;
}
else
{
}
}
catch() {}
return false;
}
the Backgroundworker :
void m_oWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If it was cancelled midway
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
btnListen.Enabled = true;
}
}
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Here you play with the main UI thread
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
if (isconnected)
{
listBox2.Items.Add(strLastDevice);
string[] ssplit = sDeviceInfo.Split(';');
foreach (string sword in ssplit)
{
listBox1.Items.Add(sword);
}
}
}
The function to attached event :
private void RegisterEvent()
{
foreach (objSDK obj in list)
{
obj.sdk.OnTransaction += () =>
{
listBox1.Items.Add("ip : " + obj.IP + " transaction");
};
}
}
You have declared m_oWorker as a local variable. I'm guessing this was a mistake ( the m_ prefix should only be used for class member variables)?
Also, you declared it within a using statement, meaning that it that the framework will call Dispose() on it at the end of the using block. Even if you held on to a reference to it (and I don't think you do) it still means its resources will be deallocated, which is probably why it isn't handling any events.
I try another workaround by using thread and task and work perfectly. Thanks for all response
I am new in server client programming so i wrote this server code
namespace TCP_SERVER
{
public partial class Form1 : Form
{
private ArrayList nSockets;
public Form1()
{
InitializeComponent();
}
public void listenerThread()
{
new TcpListener(IPAddress.Any, 8080);
TcpListener tcpListener = new TcpListener(8080);
tcpListener.Start();
while (true)
{
Socket handlerSocket = tcpListener.AcceptSocket();
if (handlerSocket.Connected)
//try
//{
{
lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.");
lock (this)
{
nSockets.Add(handlerSocket);
}
ThreadStart thdstHandler = new
ThreadStart(handlerThread);
Thread thdHandler = new Thread(thdstHandler);
thdHandler.Start();
}
//}
//catch (Exception ex)
//{
// MessageBox.Show(ex.Message);
//}
}
}
public void handlerThread()
{
Socket handlerSocket = (Socket)nSockets[nSockets.Count-1];
NetworkStream networkStream = new
NetworkStream(handlerSocket);
int thisRead=0;
int blockSize=1024;
Byte[] dataByte = new Byte[blockSize];
lock(this)
{
// Only one process can access
// the same file at any given time
Stream fileStream = File.OpenWrite(#"C:\Users\KINENE\Documents\submitted.txt");
while(true)
{
thisRead=networkStream.Read(dataByte,0,blockSize);
fileStream.Write(dataByte,0,thisRead);
if (thisRead==0) break;
}
fileStream.Close();
}
lbConnections.Items.Add("File Written");
handlerSocket = null;
}
private void Form1_Load(object sender, EventArgs e)
{
IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName());
lblStatus.Text = "My IP address is " + IPHost.AddressList[0].ToString();
nSockets = new ArrayList();
Thread thdListener = new Thread(new ThreadStart(listenerThread));
thdListener.Start();
}
}
}
i get the error on this line of code
lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.");
lock (this)
You are accessing UI elements from another thread, which is not allowed.
You should call Invoke to call the code on the right thread:
this.Invoke((MethodInvoker)delegate()
{
lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.");
});
can someone please help me out with this... I've been struggling all day.
So I'm trying to learn Async sockets which is something that's been giving me trouble.
The issue is basically the way I'm updating the ListBox with people who have joined the chat room's names:
Basically what I'm doing is having each client send "!!addlist [nickname]" when they join the server.
It's not ideal as it doesn't check for duplicates etc. but now I just want to know why it won't work.
Whenever somebody adds a name they haven't seen before, they will also send "!!addlist [nick]"
In this way, every time someone joins, the lists should be updated for everyone.
The issue seems to be that all the clients start communicating at the same time and it interferes with the buffer.
I've tried using a separate buffer for every client so that's not the issue.
I've tried using lock() but that doesn't seem to be working either.
Essentially what happens is the buffers seem to truncate; where there is data from two different people in the same buffer.
Please just tell me what I'm doing wrong with the buffers or on the client side:
Note that the async socket is using Send instead of BeginSend.
I've tried both methods and they run into the same issue... so it's probably client side?
public partial class Login : Form
{
private ChatWindow cw;
private Socket serverSocket;
private List<Socket> socketList;
private byte[] buffer;
private bool isHost;
private bool isClosing;
public void startListening()
{
try
{
this.isHost = true; //We're hosting this server
cw.callingForm = this; //Give ChatForm the login form (this) [that acts as the server]
cw.Show(); //Show ChatForm
cw.isHost = true; //Tell ChatForm it is the host (for display purposes)
this.Hide(); //And hide the login form
serverSocket.Bind(new IPEndPoint(IPAddress.Any, int.Parse(portBox.Text))); //Bind to our local address
serverSocket.Listen(1); //And start listening
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //When someone connects, begin the async callback
cw.connectTo("127.0.0.1", int.Parse(portBox.Text), nicknameBox.Text); //And have ChatForm connect to the server
}
catch (Exception) { /*MessageBox.Show("Error:\n\n" + e.ToString());*/ } //Let us know if we ran into any errors
}
public void AcceptCallback(IAsyncResult AR)
{
try
{
Socket s = serverSocket.EndAccept(AR); //When someone connects, accept the new socket
socketList.Add(s); //Add it to our list of clients
s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), s); //Begin the async receive method using our buffer
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //And start accepting new connections
}
catch (Exception) {}
}
public void ReceiveCallback(IAsyncResult AR) //When a message from a client is received
{
try
{
if (isClosing)
return;
Socket s = (Socket)AR.AsyncState; //Get the socket from our IAsyncResult
int received = s.EndReceive(AR); //Read the number of bytes received (*need to add locking code here*)
byte[] dbuf = new byte[received]; //Create a temporary buffer to store just what was received so we don't have extra data
Array.Copy(buffer, dbuf, received); //Copy the received data from our buffer to our temporary buffer
foreach (Socket client in socketList) //For each client that is connected
{
try
{
if (client != (Socket)AR.AsyncState) //If this isn't the same client that just sent a message (*client handles displaying these*)
client.Send(dbuf); //Send the message to the client
}
catch (Exception) { }
} //Start receiving new data again
s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), s);
}
catch (Exception) { /*cw.output("\n\nError:\n\n" + e.ToString());*/ }
}
public void SendCallback(IAsyncResult AR)
{
try
{
Socket s = (Socket)AR.AsyncState;
s.EndSend(AR);
}
catch (Exception) { /*cw.output("\n\nError:\n\n" + e.ToString());*/ }
}
Here is the client side:
public void getData()
{
try
{
byte[] buf = new byte[1024];
string message = "";
while(isConnected)
{
Array.Clear(buf, 0, buf.Length);
message = "";
clientSocket.Receive(buf, buf.Length, SocketFlags.None);
message = Encoding.ASCII.GetString(buf);
if (message.StartsWith("!!addlist"))
{
message = message.Replace("!!addlist", "");
string userNick = message.Trim();
if (!namesBox.Items.Contains(userNick))
{
addNick(userNick.Trim());
}
continue;
}
else if (message.StartsWith("!!removelist"))
{
message = message.Replace("!!removelist", "");
string userNick = message.Trim();
removeNick(userNick);
output("Someone left the room: " + userNick);
continue;
}
else if (!namesBox.Items.Contains(message.Substring(0, message.IndexOf(":"))))
{
addNick(message.Substring(0, message.IndexOf(":")).Trim()); //So they at least get added when they send a message
}
output(message);
}
}
catch (Exception)
{
output("\n\nConnection to the server lost.");
isConnected = false;
}
}
Here is my addNick function that seems to fix some things?
public void addNick(string n)
{
if (n.Contains(" ")) //No Spaces... such a headache
return;
if (n.Contains(":"))
return;
bool shouldAdd = true;
n = n.Trim();
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
shouldAdd = false;
if (shouldAdd)
{
namesBox.Items.Add(n);
output("Someone new joined the room: " + n);
sendRaw("!!addlist " + nickName);
}
}
I think the issue is that some of the packets are being skipped?
Maybe there's too much code in the client after Receive before it gets called again?
Should I create a separate thread for each message so that receive runs constantly? (Dumb)
Should I have my client use Async receives and sends as well?
I have a feeling that is the answer ^
With all of the checks I do, I managed to clean up the duplicate name issue... but i regularly receive messages with spaces and partial messages from other clients it seems.
Okay so, after messing with this for a long time, I have it relatively stable.
For starters, I added the following state object:
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
public bool newConnection = true;
}
This makes it easy to keep track of each connection and gives each connection its own buffer.
The second thing I did was look for a new line in each message.
I wasn't looking for this in the original code and I believe this was the root of most issues.
I also gave the responsibility of dealing with username management to the server; something that I should have done from the start obviously.
Here is the current server code:
This code is in no way perfect and I'm continuously finding new errors the more I try to break it. I'm going to keep messing with it for awhile but at the moment, it seems to work decently.
public partial class Login : Form
{
private ChatWindow cw;
private Socket serverSocket;
private List<Socket> socketList;
private byte[] buffer;
private bool isHost;
private bool isClosing;
private ListBox usernames;
public Login()
{
InitializeComponent();
}
private void Login_Load(object sender, EventArgs e)
{
ipLabel.Text = getLocalIP();
cw = new ChatWindow();
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketList = new List<Socket>();
buffer = new byte[1024];
isClosing = false;
usernames = new ListBox();
}
public string getLocalIP()
{
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}
private void joinButton_Click(object sender, EventArgs e)
{
try
{
int tryPort = 0;
this.isHost = false;
cw.callingForm = this;
if (ipBox.Text == "" || portBox.Text == "" || nicknameBox.Text == "" || !int.TryParse(portBox.Text.ToString(), out tryPort))
{
MessageBox.Show("You must enter an IP Address, Port, and Nickname to connect to a server.", "Missing Info");
return;
}
this.Hide();
cw.Show();
cw.connectTo(ipBox.Text, int.Parse(portBox.Text), nicknameBox.Text);
}
catch(Exception otheree) {
MessageBox.Show("Error:\n\n" + otheree.ToString(),"Error connecting...");
cw.Hide();
this.Show();
}
}
private void hostButton_Click(object sender, EventArgs e)
{
int tryPort = 0;
if (portBox.Text == "" || nicknameBox.Text == "" || !int.TryParse(portBox.Text.ToString(), out tryPort)) {
MessageBox.Show("You must enter a Port and Nickname to host a server.", "Missing Info");
return;
}
startListening();
}
public void startListening()
{
try
{
this.isHost = true; //We're hosting this server
cw.callingForm = this; //Give ChatForm the login form (this) [that acts as the server]
cw.Show(); //Show ChatForm
cw.isHost = true; //Tell ChatForm it is the host (for display purposes)
this.Hide(); //And hide the login form
serverSocket.Bind(new IPEndPoint(IPAddress.Any, int.Parse(portBox.Text))); //Bind to our local address
serverSocket.Listen(1); //And start listening
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); //When someone connects, begin the async callback
cw.connectTo("127.0.0.1", int.Parse(portBox.Text), nicknameBox.Text); //And have ChatForm connect to the server
}
catch (Exception) {}
}
public void AcceptCallback(IAsyncResult AR)
{
try
{
StateObject state = new StateObject();
state.workSocket = serverSocket.EndAccept(AR);
socketList.Add(state.workSocket);
state.workSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch (Exception) {}
}
public void ReceiveCallback(IAsyncResult AR)
{
try
{
if (isClosing)
return;
StateObject state = (StateObject)AR.AsyncState;
Socket s = state.workSocket;
String content = "";
int received = s.EndReceive(AR);
if(received > 0)
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, received));
content = state.sb.ToString();
if (content.IndexOf(Environment.NewLine) > -1) //If we've received the end of the message
{
if (content.StartsWith("!!addlist") && state.newConnection)
{
state.newConnection = false;
content = content.Replace("!!addlist", "");
string userNick = content.Trim();
if (isHost && userNick.StartsWith("!"))
userNick = userNick.Replace("!", "");
userNick = userNick.Trim();
if (userNick.StartsWith("!") || userNick == string.Empty || usernames.Items.IndexOf(userNick) > -1)
{
//Invalid Username :c get dropped
s.Send(Encoding.ASCII.GetBytes("Invalid Username/In Use - Sorry :("));
s.Shutdown(SocketShutdown.Both);
s.Disconnect(false);
s.Close();
socketList.Remove(s);
return;
}
usernames.Items.Add(userNick);
foreach (string name in usernames.Items)
{
if (name.IndexOf(userNick) < 0)
{
s.Send(Encoding.ASCII.GetBytes("!!addlist " + name + "\r\n"));
Thread.Sleep(10); //such a hack... ugh it annoys me that this works
}
}
foreach (Socket client in socketList)
{
try
{
if (client != s)
client.Send(Encoding.ASCII.GetBytes("!!addlist " + userNick + "\r\n"));
}
catch (Exception) { }
}
}
else if (content.StartsWith("!!removelist") && !state.newConnection)
{
content = content.Replace("!!removelist", "");
string userNick = content.Trim();
usernames.Items.Remove(userNick);
foreach (Socket client in socketList)
{
try
{
if (client != s)
client.Send(Encoding.ASCII.GetBytes("!!removelist " + userNick + "\r\n"));
}
catch (Exception) { }
}
}
else if (state.newConnection) //if they don't give their name and try to send data, just drop.
{
s.Shutdown(SocketShutdown.Both);
s.Disconnect(false);
s.Close();
socketList.Remove(s);
return;
}
else
{
foreach (Socket client in socketList)
{
try
{
if (client != s)
client.Send(System.Text.Encoding.ASCII.GetBytes(content));
}
catch (Exception) { }
}
}
}
Array.Clear(state.buffer, 0, StateObject.BufferSize);
state.sb.Clear();
s.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception) {
socketList.Remove(((StateObject)AR.AsyncState).workSocket);
}
}
public void SendCallback(IAsyncResult AR)
{
try
{
StateObject state = (StateObject)AR.AsyncState;
state.workSocket.EndSend(AR);
}
catch (Exception) {}
}
private void Login_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
this.isClosing = true;
if (this.isHost)
{
foreach (Socket c in socketList)
{
if (c.Connected)
{
c.Close();
}
}
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
serverSocket = null;
serverSocket.Dispose();
}
socketList.Clear();
}
catch (Exception) { }
finally
{
Application.Exit();
}
}
}
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
public bool newConnection = true;
}
The client code (work in progress):
public partial class ChatWindow : Form
{
private Socket clientSocket;
private Thread chatThread;
private string ipAddress;
private int port;
private bool isConnected;
private string nickName;
public bool isHost;
public Login callingForm;
private static object conLock = new object();
public ChatWindow()
{
InitializeComponent();
isConnected = false;
isHost = false;
}
public string getIP() {
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}
public void displayError(string err)
{
output(Environment.NewLine + Environment.NewLine + err + Environment.NewLine);
}
public void op(string s)
{
try
{
lock (conLock)
{
chatBox.Text += s;
}
}
catch (Exception) { }
}
public void connectTo(string ip, int p, string n) {
try
{
this.Text = "Trying to connect to " + ip + ":" + p + "...";
this.ipAddress = ip;
this.port = p;
this.nickName = n;
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (!isHost)
{
op("Connecting to " + ipAddress + ":" + port + "...");
}
else
{
output("Listening on " + getIP() + ":" + port + "...");
}
clientSocket.Connect(ipAddress, port);
isConnected = true;
if (!isHost)
{
this.Text = "Connected to " + ipAddress + ":" + port + " - Nickname: " + nickName;
output("Connected!");
}
else
{
this.Text = "Hosting on " + getIP() + ":" + port + " - Nickname: " + nickName;
}
chatThread = new Thread(new ThreadStart(getData));
chatThread.Start();
nickName = nickName.Replace(" ", "");
nickName = nickName.Replace(":", "");
if(nickName.StartsWith("!"))
nickName = nickName.Replace("!", "");
namesBox.Items.Add(nickName);
sendRaw("!!addlist " + nickName);
}
catch (ThreadAbortException)
{
//do nothing; probably closing chat window
}
catch (Exception e)
{
if (!isConnected)
{
this.Hide();
callingForm.Show();
clearText();
MessageBox.Show("Error:\n\n" + e.ToString(), "Error connecting to remote host");
}
}
}
public void removeNick(string n)
{
if (namesBox.Items.Count <= 0)
return;
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
namesBox.Items.RemoveAt(x);
}
public void clearText()
{
try
{
lock (conLock)
{
chatBox.Text = "";
}
}
catch (Exception) { }
}
public void addNick(string n)
{
if (n.Contains(" ")) //No Spaces... such a headache
return;
if (n.Contains(":"))
return;
bool shouldAdd = true;
n = n.Trim();
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
shouldAdd = false;
if (shouldAdd)
{
namesBox.Items.Add(n);
output("Someone new joined the room: " + n);
//sendRaw("!!addlist " + nickName);
}
}
public void addNickNoMessage(string n)
{
if (n.Contains(" ")) //No Spaces... such a headache
return;
if (n.Contains(":"))
return;
bool shouldAdd = true;
n = n.Trim();
for (int x = namesBox.Items.Count - 1; x >= 0; --x)
if (namesBox.Items[x].ToString().Contains(n))
shouldAdd = false;
if (shouldAdd)
{
namesBox.Items.Add(n);
//sendRaw("!!addlist " + nickName);
}
}
public void getData()
{
try
{
byte[] buf = new byte[1024];
string message = "";
while(isConnected)
{
Array.Clear(buf, 0, buf.Length);
message = "";
int gotData = clientSocket.Receive(buf, buf.Length, SocketFlags.None);
if (gotData == 0)
throw new Exception("I swear, this was working before but isn't anymore...");
message = Encoding.ASCII.GetString(buf);
if (message.StartsWith("!!addlist"))
{
message = message.Replace("!!addlist", "");
string userNick = message.Trim();
if(!namesBox.Items.Contains(userNick))
{
addNick(userNick);
}
continue;
}
else if (message.StartsWith("!!removelist"))
{
message = message.Replace("!!removelist", "");
string userNick = message.Trim();
removeNick(userNick);
output("Someone left the room: " + userNick);
continue;
}
output(message);
}
}
catch (Exception)
{
isConnected = false;
output(Environment.NewLine + "Connection to the server lost.");
}
}
public void output(string s)
{
try
{
lock (conLock)
{
chatBox.Text += s + Environment.NewLine;
}
}
catch (Exception) { }
}
private void ChatWindow_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
if(isConnected)
sendRaw("!!removelist " + nickName);
isConnected = false;
clientSocket.Shutdown(SocketShutdown.Receive);
if (chatThread.IsAlive)
chatThread.Abort();
callingForm.Close();
}
catch (Exception) { }
}
private void sendButton_Click(object sender, EventArgs e)
{
if(isConnected)
send(sendBox.Text);
}
private void sendBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (isConnected)
{
if (sendBox.Text != "")
{
send(sendBox.Text);
sendBox.SelectAll();
e.SuppressKeyPress = true;
e.Handled = true;
}
}
}
}
private void send(string t) {
try
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(nickName + ": " + t + "\r\n");
clientSocket.Send(data);
output(nickName + ": " + t);
}
catch (Exception e)
{
displayError(e.ToString());
}
}
private void sendRaw(string t)
{
try
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(t + "\r\n");
clientSocket.Send(data);
}
catch (Exception e)
{
displayError(e.ToString());
}
}
private void chatBox_TextChanged(object sender, EventArgs e)
{
chatBox.SelectionStart = chatBox.Text.Length;
chatBox.ScrollToCaret();
}
private void sendBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
e.SuppressKeyPress = true;
}
}
To do:
Add invokes, more delegates, do some more QA and find out what breaks it.
Also, I believe there's still the possibility of packet loss due to the client addlist functions being in the read loop. I believe this is why the "crappy hack" using Thread.Sleep(10) in the server callback for name population is an issue.
I think it might be better to either pass the command off to another thread while continuing to read or have the client tell the server it's ready for another name.
Otherwise, there might be some data loss during name updates.
The other thing is that, as was said in the comments above, delegates should be used when updating the UI objects (chatbox and listbox). I wrote the code for these but ultimately removed it because there was no noticeable change and I wanted to keep it simple.
I do still use an object lock when outputting text to the chatbox, but there's no noticeable difference there.
The code should be added as not using delegates is potentially problematic, but I literally caught the chat box in an infinite loop of updates without issue.
I tried breaking it with telnet and was successful so I added a newConnection property to the StateObject to ensure that each client can only send "!!addlist" once.
There are, of course, other ways to abuse the server by creating a client that joins and leaves repeatedly, so ultimately I will probably end up passing the !!removelist handling to the server instead of leaving it up to the client.
I'm new to sockets so I tried to create a server and a client that exchange messages. I created one in C# but it gave me weird error which it once I start the server it freezes and "not responding" message appears ... same happens with client when I connect the server but the problem is when I close any of them .. the other application have the updates shown up so idk what the problem is anyways here are the codes U used
Server class
Socket Soc;
static ushort MaxClients = 1000;
static List<Socket> ClientList = new List<Socket>(MaxClients);
static bool ServerStarted;
public Server()
{
InitializeComponent();
button1.Enabled = false;
button2.Enabled = false;
}
private void button1_Click(object sender, EventArgs e) // Send
{
string MessageToSend = textBox1.Text;
byte[] Buffer = Encoding.Default.GetBytes(MessageToSend);
foreach (var client in ClientList)
{
Soc.Send(Buffer, 0, Buffer.Length, SocketFlags.None);
}
textBox2.Text += " Message Sent To Clients : " + MessageToSend + Environment.NewLine;
}
private void button3_Click(object sender, EventArgs e) // Start
{
StartServer("25.21.113.163", 5000);
}
private void button2_Click(object sender, EventArgs e) // Stop
{
CloseServer();
}
private void button4_Click(object sender, EventArgs e) // Exit
{
CloseServer();
Application.Exit();
}
public void StartServer(string Ip, ushort Port)
{
Soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Soc.Bind(new IPEndPoint(IPAddress.Parse(Ip), Port));
textBox2.Text += " Server Is Created On Ip : " + Ip + ", Port : " + Port + Environment.NewLine;
Soc.Listen(MaxClients);
textBox2.Text += " Server Is Listening to Clients Now... " + Environment.NewLine;
ServerStarted = true;
button1.Enabled = true;
button2.Enabled = true;
button3.Enabled = false;
label3.Text = ClientList.Count.ToString() + "/" + MaxClients;
ReceiveData();
}
public void ReceiveData()
{
while (true)
{
var Client = Soc.Accept();
ClientList.Add(Client);
label3.Text = ClientList.Count.ToString() + "/" + MaxClients;
textBox2.Text += " Client Located At Ip : " + Client.RemoteEndPoint.ToString().Split(':')[0].ToString() + " Is Now Connected To Server " + Environment.NewLine;
while (true)
{
byte[] ReceivedBytes = new byte[1024];
int ReceivedDataLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None);
string MessageFromClient = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedDataLength);
textBox2.Text += " Message Sent to Server : " + MessageFromClient + Environment.NewLine;
}
}
}
public void CloseServer()
{
Soc.Close();
ServerStarted = false;
textBox2.Text += " Server Is Closed Now... " + Environment.NewLine;
button3.Enabled = true;
button2.Enabled = false;
button1.Enabled = false;
}
Client class
Socket Client;
public Form1()
{
InitializeComponent();
button1.Enabled = false;
button2.Enabled = false;
}
private void button1_Click(object sender, EventArgs e) // Send
{
string MessageToSend = textBox2.Text;
byte[] Buffer = Encoding.Default.GetBytes(MessageToSend);
Client.Send(Buffer, 0, Buffer.Length, SocketFlags.None);
textBox1.Text += " Sent Message To Server Is : " + MessageToSend + Environment.NewLine;
}
private void button2_Click(object sender, EventArgs e) // LogOut
{
ClientClose();
}
private void button3_Click(object sender, EventArgs e) // Connect
{
ConnectToServer("25.21.113.163", 5000);
}
private void button4_Click(object sender, EventArgs e) // Exit
{
ClientClose();
Application.Exit();
}
public void ConnectToServer(string Ip, ushort Port)
{
try
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Client.Connect(Ip, Port);
textBox1.Text += " You Are Now Connected To Server Hosted On Ip : " + Client.RemoteEndPoint + Environment.NewLine;
button1.Enabled = true;
button2.Enabled = true;
button3.Enabled = false;
ReceiveData();
}
catch
{
textBox1.Text += " Server In Offline Now " + Environment.NewLine;
}
}
public void ReceiveData()
{
while (true)
{
byte[] ReceivedBytes = new byte[1024];
int ReceivedBytesLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None);
string ReceivedMessage = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedBytesLength);
textBox1.Text += " Received Message From Server Is : " + ReceivedMessage + Environment.NewLine;
}
}
public void ClientClose()
{
button1.Enabled = false;
button2.Enabled = false;
button3.Enabled = true;
Client.Dispose();
Client.Close();
textBox1.Text += " You Are Disconnected From Server" + Environment.NewLine;
}
I'd like to know what did I do wrong? And how can I get rid of that silly "Not Responding" state of both applications?
First, Let's make a corrections on your code so that it works, thank I'd give some Asynchronous Socket tutorials which is a lot easier than Synchronous.
Your problem is in this line:
public void ReceiveData()
{
while (true)
{
var Client = Soc.Accept();
ClientList.Add(Client);
label3.Text = ClientList.Count.ToString() + "/" + MaxClients;
textBox2.Text += " Client Located At Ip : " + Client.RemoteEndPoint.ToString().Split(':')[0].ToString() + " Is Now Connected To Server " + Environment.NewLine;
while (true)
{
byte[] ReceivedBytes = new byte[1024];
int ReceivedDataLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None);
string MessageFromClient = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedDataLength);
textBox2.Text += " Message Sent to Server : " + MessageFromClient + Environment.NewLine;
}
}
}
This is because of 2 reasons:
1) You must listen to incoming connection to a separate thread.
2) You must listen to each client in a separate thread too, so they don't block each other. In your example second while(true) which is listening for client is blocking server socket from accepting other clients. Refactor it to:
public void ReceiveData()
{
new Thread(() =>
{
while (true)
{
var Client = Soc.Accept();
ClientList.Add(Client);
label3.Text = ClientList.Count.ToString() + "/" + MaxClients;
textBox2.Text += " Client Located At Ip : " + Client.RemoteEndPoint.ToString().Split(':')[0].ToString() + " Is Now Connected To Server " + Environment.NewLine;
new Thread(() =>
{
while (true)
{
byte[] ReceivedBytes = new byte[1024];
int ReceivedDataLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None);
string MessageFromClient = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedDataLength);
textBox2.Text += " Message Sent to Server : " + MessageFromClient + Environment.NewLine;
}
}).Start();
}
}).Start();
}
This approach uses separate thread for each client to process received data from client.
I also added code for client app:
public void ReceiveData()
{
new Thread(() =>
{
while (true)
{
byte[] ReceivedBytes = new byte[1024];
int ReceivedBytesLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None);
string ReceivedMessage = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedBytesLength);
textBox1.Text += " Received Message From Server Is : " + ReceivedMessage + Environment.NewLine;
}
}).Start();
}
In the future have a look Asynchronous Sockets and you will no more need handling multithreading issues.
http://msdn.microsoft.com/en-us/library/fx6588te.aspx
http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx
EDIT Updated client/ser
I am working on this GUI for serial port application. I recently added stop and wait protocols to the application. Surprisingly my disconnect button stopped working. I have thought through the logic and I have not been able to find the problem.
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
public bool packetreceived = false;
private SerialPort sp = null; //<---- serial port at form level
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
//delegate variable to disconnect
public AddDataDelegate disconnectDelegate = null;
public void AddDataMethod(String myString)
{
richTextBox1.AppendText(myString);
}
/**
* Takes byte array and returns a string representation
*
*/
public String parseUARTData(byte[] data)
{
if (data.Length == 11)
{
String rv = "";
DataFields d = new DataFields();
if (!packetreceived)
{
d = mainLogic.parseData(data);
packetreceived = true;
}
//TODO
System.Threading.Thread.Sleep(5000);
if (d.sequence == 0)
{
sp.Write("1\r\n");
}
else
{
sp.Write("0\r\n");
}
packetreceived = false;
//now display it as a string
rv += STR_OPCODE + " = " + d.opcode + "\n";
rv += STR_CRC + " = " + d.crc + "\n";
rv += STR_SEQ + " = " + d.sequence + "\n";
rv += STR_FLAGS + " = " + d.flags + "\n";
rv += STR_TEMP + " = " + d.temperature + "\n";
rv += STR_HUMID + " = " + d.humidity + "\n";
rv += STR_PH + " = " + d.ph + "\n";
return rv + "\n\n";
}
else
{
return Encoding.ASCII.GetString(data);
}
}
private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string s = sp.ReadExisting();
if (disconnectDelegate != null)
{
disconnectDelegate.Invoke(s);
}
richTextBox1.Invoke(this.myDelegate, new Object[] { parseUARTData(Encoding.ASCII.GetBytes(s)) });
}
private void button1_Click(object sender, EventArgs e)
{
connect.Enabled = false;
try
{
// open port if not already open
// Note: exception occurs if Open when already open.
if (!sp.IsOpen)
{
//sp.PortName = this.comboBox1.SelectedItem.ToString();
sp.Open();
}
// send data to port
sp.Write("####,###########\r\n");
disconnect.Enabled = true;
}
catch (Exception)
{
// report exception to user
Console.WriteLine(e.ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
connect.Enabled = true;
try
{
// open port if not already open
// Note: exception occurs if Open when already open.
if (sp.IsOpen)
{
// send data to port
sp.Write("+++\r\n");
//add the delegate
disconnectDelegate = new AddDataDelegate(onDisconnect);
//sp.WriteTimeout = 500;
// sp.Write("####,0\r\n");
}
}
catch (Exception)
{
Console.WriteLine(e.ToString());
}
finally
{
disconnect.Enabled = false;
}
}
public void OnApplicationExit(object sender, EventArgs e)
{
sp.Close();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//foreach (string port in ports)
//{
// comboBoxSerialPorts.Items.Add(port);
//}
}
private void onDisconnect(string msg)
{
string trimmedMsg = msg.Trim();
if (trimmedMsg.Equals("OK"))
{
//send the second time
sp.Write("##,0\r\n");
//null the object
disconnectDelegate = null;
}
}
private void comPort_Click(object sender, EventArgs e)
{
try
{
if (sp.IsOpen)
{
//send data to port
sp.Write("1\r\n");
MessageBox.Show("bluetooth is transmitting data...");
//message box telling user that you are asking for data.
}
}
catch (Exception)
{
// report exception to user
Console.WriteLine(e.ToString());
}
}