coldfusion244 Posted November 29, 2004 Posted November 29, 2004 Hello everyone, I am attempting to make a client/server program using sockets, but the program hangs on the Socket.AcceptConnection() line until there is a connection made. I was searching around and found some code on how to do it, but it used neither the AcceptConnection using a listener nor the read.ReadString(). I was wondering if anyone knows of some good tutorials or has some commented socket code laying around. MSDN was a waste of time, since I am new to network programming. I want to have multiple clients connected to the server at one time, and be able to send information back and forth. Not looking for many clients, max will probably be 50, if that. I was using the following code: [CS] private void wfc() { TcpListener listener; try { while(true) { listener = new TcpListener(50000); listener.Start(); connection = listener.AcceptSocket(); clsClient CC = new clsClient(connection, this.t1); listener.Stop(); listener = null; } } catch(Exception e) { t1.Text = e.ToString(); } } [/CS] Thanks, -Cold Quote -Sean
coldfusion244 Posted November 29, 2004 Author Posted November 29, 2004 A waste of time? I am just having the hardest time understanding it. The easiest way I found was the way I posted above. I just don't really get teh asycnhronous part. For example, you have to have a delegate? Ugh, it's going to be a long night. Quote -Sean
coldfusion244 Posted November 29, 2004 Author Posted November 29, 2004 HJB, the examples I looked at are poorly commented. If you could make a small example of the asynchronous or have an example that is commented well handy I would greatly appreciate it :D Quote -Sean
HJB417 Posted November 29, 2004 Posted November 29, 2004 public void Asynchronous_wfc() { //make a tcp socket Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //bind it to all nics on port 11000. socket.Bind(new IPEndPoint(IPAddress.Any, 11000)); //listen for connections. socket.Listen(5); //method returns immediately but 'SomeoneConnected' will be invoked //when someone connects. socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket); } private void SomeoneConnected(IAsyncResult result) { //result.AsyncState stores the 2nd argument of BeginAccept //in this case, a socket, because I made it store a socket. Socket socket = (Socket) result.AsyncState; //you need to call end accept to get the connected socket. Socket remoteEnd = socket.EndAccept(result); //call begin accept again to get the next incoming connection. socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket); } What's so bad about delegates? Quote
coldfusion244 Posted November 29, 2004 Author Posted November 29, 2004 Thanks HJB, the way you explained it was, well, the best i've seen! I am starting to understand it now. So basically I am going to have to do the same thing for reading and writing data... I would have to make all of those using the same argument list so that they would be asynchronous... Quote -Sean
HJB417 Posted November 30, 2004 Posted November 30, 2004 yes, there's more to know about asynchronous operations in the bcl. but that's the basic. There's stuff like the waithandle. e.x.: IAsynchResult result = socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket); //the 'WaitOne' will not return until a connection attempt is receievd. result.AsyncWaitHandle.WaitOne(); Quote
coldfusion244 Posted December 1, 2004 Author Posted December 1, 2004 Still confuzzled Ok Hjb, I attempted for two days now to get the receive and send to work, no such luck (I must be brain dead). In the server portion I have this: [CS] private void SomeoneConnected(IAsyncResult result) { //result.AsyncState stores the 2nd argument of BeginAccept //in this case, a socket, because I made it store a socket. Socket socket = (Socket) result.AsyncState; //you need to call end accept to get the connected socket. Socket remoteEnd = socket.EndAccept(result); t1.Text += "\r\nSomeone Connected!"; //call begin accept again to get the next incoming connection. byte[] buffer = System.Text.Encoding.UTF8.GetBytes(""); socket.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(CheckPackets),socket); socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket); } private void CheckPackets(IAsyncResult result) { byte[] buffer = System.Text.Encoding.UTF8.GetBytes(""); Socket socket = (Socket) result.AsyncState; int dsocket = socket.EndReceive(result); socket.Receive(buffer); t1.Text+="\r\n" + System.Text.Encoding.UTF8.GetString(buffer); socket.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets),socket); } [/CS] In the client part I have: [CS] private void Connected(IAsyncResult result) { //result.AsyncState stores the 2nd argument of BeginAccept //in this case, a socket, because I made it store a socket. Socket socket = (Socket) result.AsyncState; //you need to call end accept to get the connected socket. socket.EndConnect(result); label1.Text += "\r\nWe Connected!"; byte[] msg = System.Text.Encoding.UTF8.GetBytes("Test message!"); int i = socket.Send(msg); Console.WriteLine("Sent " + i + " bytes of data."); } [/CS] The client responds as sending 13 bytes of data, but in the server program I receive the error: An unhandled exception of type 'System.InvalidOperationException' occurred in system.dll Additional information: AcceptCallback What am I doing wrong?! Quote -Sean
HJB417 Posted December 1, 2004 Posted December 1, 2004 'remoteEnd' is what is connected to the "remote end", not 'socket'. private void SomeoneConnected(IAsyncResult result) { //result.AsyncState stores the 2nd argument of BeginAccept //in this case, a socket, because I made it store a socket. Socket socket = (Socket) result.AsyncState; //you need to call end accept to get the connected socket. Socket remoteEnd = socket.EndAccept(result); t1.Text += "\r\nSomeone Connected!"; //call begin accept again to get the next incoming connection. byte[] buffer = System.Text.Encoding.UTF8.GetBytes(""); remoteEnd.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(CheckPackets),socket); socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket); } Quote
coldfusion244 Posted December 1, 2004 Author Posted December 1, 2004 (edited) Ok, I can send data between the two programs, but it only sends it 1 byte at a time... Is there any way to send it all at once? Edited December 2, 2004 by coldfusion244 Quote -Sean
coldfusion244 Posted December 2, 2004 Author Posted December 2, 2004 Anyone have an idea? Quote -Sean
HJB417 Posted December 2, 2004 Posted December 2, 2004 I think you need to post reproduceable code. Quote
coldfusion244 Posted December 2, 2004 Author Posted December 2, 2004 I think you need to post reproduceable code. HJB, I do appreciate all the time and posts you made! ;) Screenshot - Click Here Server Code: [CS] private void SomeoneConnected(IAsyncResult result) { //result.AsyncState stores the 2nd argument of BeginAccept //in this case, a socket, because I made it store a socket. Socket socket = (Socket) result.AsyncState; //you need to call end accept to get the connected socket. Socket remoteEnd = socket.EndAccept(result); t1.Text += "\r\nSomeone Connected!"; //call begin accept again to get the next incoming connection. byte[] buffer = System.Text.Encoding.UTF8.GetBytes(""); remoteEnd.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(CheckPackets),remoteEnd); socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket); } private void CheckPackets(IAsyncResult result) { //byte[] buffer = System.Text.Encoding.UTF8.GetBytes("no"); Socket socket = (Socket) result.AsyncState; int dsocket = socket.EndReceive(result); if (dsocket<=0) { } else { t1.Text+="\r\nReceived " + dsocket + " bytes of data." + " - " + System.Text.Encoding.UTF8.GetString(buffer); } socket.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets),socket); } [/CS] Client code: [CS] /********************/ byte[] msg = System.Text.Encoding.UTF8.GetBytes("Test message!"); public Socket mysocket; /********************/ private void Connected(IAsyncResult result) { //result.AsyncState stores the 2nd argument of BeginAccept //in this case, a socket, because I made it store a socket. Socket socket = (Socket) result.AsyncState; //you need to call end accept to get the connected socket. socket.EndConnect(result); mysocket = socket; label1.Text += "\r\nWe Connected!"; sendstuff(mysocket); } private void button2_Click(object sender, System.EventArgs e) { sendtuff(mysocket); } private void sendstuff(Socket socket) { socket.BeginSend(msg,0,msg.Length,System.Net.Sockets.SocketFlags.None,new AsyncCallback(sending),socket); } private void sending(IAsyncResult ar) { Socket socket = (Socket) ar.AsyncState; int i = socket.EndSend(ar); Console.WriteLine("Sent " + i + " Bytes."); } [/CS] Quote -Sean
HJB417 Posted December 2, 2004 Posted December 2, 2004 private void SomeoneConnected(IAsyncResult result) { //result.AsyncState stores the 2nd argument of BeginAccept //in this case, a socket, because I made it store a socket. Socket socket = (Socket) result.AsyncState; //you need to call end accept to get the connected socket. Socket remoteEnd = socket.EndAccept(result); t1.Text += "\r\nSomeone Connected!"; //call begin accept again to get the next incoming connection. byte[] buffer = new byte[65536]; // instead of storing just the 'remote end' // i'm going to store an array that contains the 'remote end' and // the array the socket will write/store the received data. remoteEnd.BeginReceive(buffer, 0, buffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets), new object[] {remoteEnd, buffer}); socket.BeginAccept(new AsyncCallback(SomeoneConnected), socket); } private static void CheckPackets(IAsyncResult result) { int amtRecvd = socket.EndReceive(result); // I access the data array to get the that was array // created in SomeoneConnected(IAsyncResult). object[] info = (object[]) result.AsyncState; Socket remoteEnd = (Socket) info[0]; byte[] buffer = (byte[]) info[1]; if (amtRecvd == 0) { //if amtRecvd == 0, all data has been receieved and the connection has been closed try { remoteEnd.Shutdown(SocketShutdown.Both); } finally { remoteEnd.Close(); } } else { t1.Text+="\r\nReceived " + amtRecvd + " bytes of data." + " - " + System.Text.Encoding.UTF8.GetString(buffer, 0, buffer.Length); byte[] buffer = new byte[65536]; remoteEnd.BeginReceive(buffer, 0, buffer.Length, System.Net.Sockets.SocketFlags.None, new AsyncCallback(CheckPackets), new object[] {remoteEnd, buffer}); } } Quote
coldfusion244 Posted December 3, 2004 Author Posted December 3, 2004 Ok, everything works now! Thanks for all you're help HJB, I appreciate it very much! The last question I have is, that when I run the server everythign is fine, then when a user connects it instantly jumps to 99% processor usage and slows my whole system down. Any idea why? Quote -Sean
HJB417 Posted December 3, 2004 Posted December 3, 2004 I don't know why it would do that. if you could post reproduceable code, i might be able to find out why. Quote
coldfusion244 Posted December 4, 2004 Author Posted December 4, 2004 Which part of the code? Should I just have the connection part or all of it? I tried to debug it, although nothing I did seemed to help :confused: Quote -Sean
HJB417 Posted December 4, 2004 Posted December 4, 2004 post all the code needed to recreate the problem or create a new solution that can do it. Quote
coldfusion244 Posted December 5, 2004 Author Posted December 5, 2004 I am so stupid.... I had the function sending blank messages. I didn't put the beginsend inside the braces! so whether or not information was there it sent itself in a constant never ending loop! wow, I think i've been staying up way too late... :p Thanks for everything again HJB, you're a huge asset to the community! -THREAD RESOLVED- Quote -Sean
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.