Find the answer to your Linux question:
Results 1 to 7 of 7
Hi guys, I am writing a small TCP socket program. It connects users to IMAP server(Telnet). It has fixed number of threads, means it does not create a new thread ...
  1. #1
    Just Joined!
    Join Date
    Mar 2010
    Posts
    3

    TCP socket APP

    Hi guys,
    I am writing a small TCP socket program. It connects users to IMAP server(Telnet). It has fixed number of threads, means it does not create a new thread when a new user connects.
    These threads acts as service threads which perform small tasks and passes the control to next thread.
    1.First question: Is this approach is good enough or should I make new thread for every user. The problem I see in that they have to carry the same functions and that means they will be in block state anyways and
    one thread is executing, therefor writing small service threads seemed better to me.
    Users limit is thought to be 100 users.

    2. The other question is I am using only one socket(local) where all users communicate. I tested little bit
    and it seemed okay. Is using one socket for this application is good or should I use multiple sockets?
    How many connections can a socket queue in?

    Best Regards,

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    You need to read your TCP/IP socket api documentation more closely, otherwise you would realize that when you call the listen() function it takes an argument for a backlog which is how many pending connections it will support. Once you call accept(), the first connection request on the queue will be removed and given its own socket for communicating with that user/client application. If you don't create a new thread for that user (which is the preferred method), then you will need to keep track of what you are doing for whom in more detail so that when you reply to the client socket that accept() created you wlil be sending back the correct data.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Just Joined!
    Join Date
    Mar 2010
    Posts
    3

    Thread pooling vs. Thread per user

    Hey Rubberman,
    Thanks for replying. Yes, I looked into the doc. lil bit. I am currently setting
    the backlog as zero which per doc says will take the optimum number of requests in queue.
    I am not starting new threads for every user because its the same code for each thread to execute. I mean if e.g. there is a search function and 5 search requests comes then every thread has to wait until other finishes. Rather, I have divided
    search functionality and given it to different threads( thread pool) so that when many requests come, these threads will process each request partially before passing it to next thread and take the next request in queue and so on. In this way the user can get response at better rate i guessed. I hope i explained it correctly.

    For user data I have linked list where every new user is added along with its data,
    and is deleted when no longer required.
    Upon authentication a hash word is generated and next time user send this hash word along with request. I look if this hash word exist for this user in my linked list, and process the request.

    My question is about the concept that I am using only 1 socket for listening. I have max scenario of 100 users interacting at one peek time. So should i consider 1 socket solution safe or should I use multiple sockets to listen the request.

    You said creating thread per user is better, can you reason it?

    Many thanks for your input.
    nadz

  4. #4
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    1. If each user is associated with a separate thread, and assuming that the user data information (can be in a linked list managed by main thread that accepts the connection requirests) for each connection is a separate data item (eliminating the need for mutex or semaphore locks on this data, then each user search option can be executing simultaneously, taking maximum advantage of multiple processors or processor cores.

    2. The queue that is established by the listen() function is only for the number of unsatisfied connection requests that are outstanding, not the total number of users or user requests that are be executed. This number is dependent upon the system and kernel version, but for most it is 128.

    So, what is generally considered standard practice for a TCP/IP server, you have a tight loop that does the following up to the maximum number of simultaneous connections you want to support:

    1. If connection limit is reached, wait for signal to start accepting more requests.
    2. accept() connection request
    3. create data element for connection and dispatch thread

    You need a single separate thread to wait() on the termination of the dispatched threads so that their resources are cleaned up, otherwise your server will eventually fail from lack of certain resources (process/thread ids, etc). This thread is also responsible to know when the root thread is not accepting new connections and signal it when it should start accepting more connection requests.

    Final note. If you aren't using threads, then you can fork off separate processes for each accepted request. This is the way we used to do things before POSIX threads were so standard and robust. I still do that in cases where the overhead and complexity of data locking is excessive because it really simplifies the programming effort, reducing by orders of magnitude the likelihood of deadlocks and race conditions and the difficulty in detecting them.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  5. #5
    Just Joined!
    Join Date
    Mar 2010
    Posts
    3

    Potiner function

    Thanks for your reply rubberrman,
    I have few confusions: In case I create a new thread for every new connection(user)
    do I have to create a new thread function too(function to be threaded) for each new thread.
    If I use only one thread function for all new threads, won't they be waiting till
    one thread is done doing its job and returned the control. (Which means one request at a time.)

    for instance.

    got new user -> create new thread A
    thread function()
    {
    thread A waiting
    }

    got new user -> create new thread B
    thread function()
    {
    thread A waiting
    thread B waiting
    }

    search request for Thread B
    search request for Thread A

    thread function()
    {
    thread A waiting
    thread B running
    }

    search()
    {
    thread B executing search
    code
    }

    I hope I made it clear.

    Thanks for your help.
    Waiting for your reply.
    Regards.

    N.B.
    The machine is a single processor with max 2 GB RAM.

  6. #6
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    Threads are lightweight and share memory with all members of the root process, except local variables. The pthread_create() function takes 4 arguments, the last of which is an opaque pointer that you provide which is passed to the start routine (the 3rd argument). That would likely be, in your case, a pointer to the structure that is associated with this connection. It can contain the reply socket, a pointer to some sort of data, or whatever else is appropriate to your needs. Since while it is running only that thread will access this structure, you don't need to worry about locking it.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  7. #7
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
    Posts
    8,974
    If I use only one thread function for all new threads, won't they be waiting till one thread is done doing its job and returned the control. (Which means one request at a time.)
    These functions are supposed to be reintrant. That means each thread can be calling these functions, unless you provide some sort of on-entry guard that serializes access to them, which is kind of contrary to your purposes I think. You can pass the thread's data structure pointer to them that you passed to pthread_create() as a context variable and get whatever thread-specific data you need from that. As mentioned in my last post, that could include the client socket, a thread-private socket to the search engine, some sort of buffer(s) for data to return to the client, etc. What is up to you. You just want to make sure that any data accessed in these functions is specific to the thread calling it, which means eliminating use of local static variables, writable global variables (read-only is ok) that can't be read+updated atomically (see use of the volatile keyword for C/C++).

    Anyway, writing thread-safe code isn't simple, and there are system library functions that aren't thread-safe, though they usually have versions that are thread-safe. The thread-safe version of those will have an _r at the end of the function name, which stands for reintrant. This is why it is often better to use what I call coarse-grained multi-threading by use of forked processes. Context switching is slower, but on modern multi-core architectures this is not usually a major problem. It eliminates the need to worry about reintrancy and data access safety pretty much altogether.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...