Link to home
Start Free TrialLog in
Avatar of saragani
saragani

asked on

Single connection server using sockets

I have a problem which is bugging me since I started working with sockets in .Net (in VB6 I would not have this problem. I need to create a Serer that accepts a connection from 1 client only.

This is s sample code for the connection process...

The problem is that as you can see is that even though I have socketListener.Listen(0); , I still can have more than 1 client connected to the server.

I mean:
Client1 connects to the server, he gets "Hello World".
Client2 connects to the server and the connection stays opened for the client (The server doesn't rejects the connection).

If a 3rd client tries to connect to the server then he would get:
"Connecting to 192.168.1.100..."

If I close the connection of Client1 then now Client2 continues with the Accept and also gets "Hello World".


This is not what I want.
I want that Client2 will also get "Connecting to 192.168.1.100..."


I had "solved this problem in the past by doing:
                socketWorker = socketListener.EndAccept(ar);
                IPEndPoint ep = socketWorker.RemoteEndPoint as IPEndPoint;
                RemoteIP = ep.Address.ToString();
                socketListener.Close();

By this way I close the Listener and therefore no other connection is allowed. But then when the Listener needs to return to listen after the client closed the connection, I need to create a new socketListener object and bind it again.
This works, but after lots of connect disconnect and Listen cycles, something get screwed, and I can't get back to Listen.

(I get some exceptions on the Connect, or when I try to Bind the port, I get that the port is already in use).

How can I make yhe code so it will only accept connection from 1 client only and all other connections will be rejected ("Connecting to 192.168.1.100...")?

Thanks.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Diagnostics;

namespace TcpListen
{
    public partial class Form1 : Form
    {
        public event EventHandler OnConnect;
        public event EventHandler OnClose;
        public delegate void DataReceivedDelegate(object sender, byte[] receivedBytes);
        public event DataReceivedDelegate OnDataReceived;
        public delegate void SocektErrorDelegate(object sender, SocketError socketError);
        public event SocektErrorDelegate OnSocektError;


        private Socket socketListener;
        private Socket socketWorker;
        private object objectLocker = new object();
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ep = new IPEndPoint(IPAddress.Any, 1234);
            try
            {
                socketListener.Bind(ep);
            }
            catch
            {
                throw;
            }

            socketListener.Listen(0);
            socketListener.BeginAccept(onConnect, null);
        }

        private void onConnect(IAsyncResult ar)
        {
            try
            {
                lock (objectLocker)
                {
                    socketWorker = socketListener.EndAccept(ar);
                    IPEndPoint ep = socketWorker.RemoteEndPoint as IPEndPoint;
                    try
                    {
                        Send(ASCIIEncoding.ASCII.GetBytes("Hello World"));
                    }
                    catch
                    {
                    }
                    waitForData();
                }     
            }
            catch (Exception ex)
            {
            }
        }

        private void waitForData()
        {
            SocketState socketState = new SocketState();
            socketState.Socket = socketWorker;
            socketState.ReceivedData = new byte[1024];
            socketWorker.BeginReceive(socketState.ReceivedData, 0, socketState.ReceivedData.Length, SocketFlags.None, out socketState.ErrorCode, onDataReceived, socketState);
        }

        private void onDataReceived(IAsyncResult ar)
        {
            SocketState socketState = null;
            try
            {
                socketState = (SocketState)ar.AsyncState;
                int cbRead = 0;
                cbRead = socketWorker.EndReceive(ar);
                if (cbRead > 0)
                {
                    if (OnDataReceived != null)
                    {
                        byte[] temp = new byte[cbRead];
                        Array.Copy(socketState.ReceivedData, 0, temp, 0, cbRead);
                        OnDataReceived(this, temp);
                    }
                    waitForData();
                }
                else
                {
                    if (OnClose != null)
                    {
                        OnClose(this, null);
                    }
                    socketListener.BeginAccept(onConnect, null);
                }
            }
            catch (ObjectDisposedException od)
            {

                if (OnClose != null)
                {
                    OnClose(this, null);
                }
                socketListener.BeginAccept(onConnect, null);
            }
            catch (SocketException se)
            {
                if (OnSocektError != null)
                {
                    OnSocektError(this, socketState.ErrorCode);
                }
                socketListener.BeginAccept(onConnect, null);
            }
            catch (Exception ex)
            {
                if (OnSocektError != null)
                {
                    OnSocektError(this, socketState.ErrorCode);
                }
                socketListener.BeginAccept(onConnect, null);
            }
        }

        public void Send(byte[] buffer)
        {
            try
            {
                socketWorker.Send(buffer);
            }
            catch
            {
                throw;
            }
        }

        private class SocketState
        {
            public Socket Socket { get; set; }
            public byte[] ReceivedData { get; set; }
            public SocketError ErrorCode;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (socketWorker != null)
            {
                try
                {
                    socketWorker.Close();
                }
                catch { }
            }
        }
    }
}

Open in new window

Avatar of saragani
saragani

ASKER

If the problem is still now understood, I want the backlog to be 0 not 1.
Even though I write 0 on socketListener.Listen(0), it ignores me and still saves a place in the queue for 1 backlog connection.

The code acts the same if I write ether socketListener.Listen(0), or socketListener.Listen(1).

I don't want backlog connections at all. How do I solve that?
ASKER CERTIFIED SOLUTION
Avatar of akhileshcoer
akhileshcoer
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ok, can you give me a code example, cause I'm a little confused....
I'm not sure which socked I need to close.

Assuming someone (which is the first guy, Client1) tries to connect the server, I will not close his connection.

If not another guy tries to connect the server (Client2) i can't close his socket since it is not an active connection (The connection is half opened. I don't get the Asych Callback of the BeginAccept).

Why I can't do what is possible in VB6??
Is .Net that lame?
it is not the .net lame it the way we you are using socket and listener. In VB6 code you are closing the listener which will give "connection refused" kind of errors.
This kind of logic you can implement in .net also. but i think keeping listener active and closing socket should do you job.

you can just call socket.close() to close the socket and check listener.pending() to check if there are any pending request in pipeline. if yes, then its you call what to do with that