Learning about thread programming in Linux

Source: Internet
Author: User
Tags sendmsg socket error
For more information about Linux Thread Programming-Linux general technology-Linux programming and kernel, see the following. I recently studied Thread Programming in Linux. In my system environment, Fedora 7.0, I designed a program like this:

This is a background service system that provides two external service interfaces. After receiving a request from the Client, it searches for the relevant data in the database. If it is OK, it is forwarded to another server for processing, then forward the processing to the client.

This Service uses the Socket persistent connection mode before connecting to another server. In the configuration file, you can define the number of connections. After the service is started, so many threads are automatically generated, the message queue mode is currently used for communication between threads.

After the service is started, start the other two threads, start the Socket service respectively, and wait for the client to connect to the request.

Another thread is started to record the communication data. Whether to enable this function can be determined by the configuration file.

The main thread is responsible for monitoring the status of these sub-threads. If a thread terminates abnormally or is not started for some reason, the monitoring thread can be started regularly and monitored regularly using alarm.

In addition, I wrote a test applet, which is quite simple. I entered the number of concurrent programs through the command line, and the number of tests executed by each sub-process. The source code is as follows:
CODE: # include

Extern int errno;

Void workthread (struct sockaddr_in sin, int loopnum)
{
CLIENTPKG cLientPkg;
Char SendMsg [257];
Char RecvMsg [257];
Int rc = 0, j, nReturn, nLen, bJump = 0;
Int ii;

For (ii = 1; ii <= loopnum; ii ++)
{
Printf ("ThreadId = % d, loopnum: % d \ n", (int) getpid (), ii );
Rc = socket (PF_INET, SOCK_STREAM, 0 );
If (rc <0)
{
Printf ("Build socket Err: % d, % s! \ N ", errno, strerror (errno ));
Exit (0 );
}

If (connect (rc, (struct sockaddr *) & sin, sizeof (sin ))! = 0)
{
Printf ("connect fail! \ N ");
Exit (0 );
}

Memset (& cLientPkg, 0, sizeof (cLientPkg ));
Memcpy (cLientPkg. pPID, "0000", 4 );
CLientPkg. cCommand = 0x66;
Memcpy (cLientPkg. pAreaID, "0000", 4 );
Memcpy (cLientPkg. Fig, "0000", 4 );
Memcpy (cLientPkg. pOperater, "00000", 5 );
Memcpy (cLientPkg. pMachID, "0121000100", 10 );
Memcpy (cLientPkg. pQueryStart, "20030801", 8 );
Memcpy (cLientPkg. pQueryEnd, "20031010", 8 );
Memcpy (SendMsg, & cLientPkg, sizeof (cLientPkg ));

If (send (rc, SendMsg, 256, 0) <0)
{
Printf ("Send Message fail. \ n ");
Exit (0 );
}

Do
{
NLen = 0;
Do
{
NReturn = recv (rc, RecvMsg + nLen, 256-nLen, 0 );
If (nReturn <0)
{
Printf ("Recv errno = % d \ n", errno );
Close (rc );
Exit (0 );
}
NLen + = nReturn;
} While (RecvMsg [6]! = (Char) 0xff );

If (RecvMsg [6]! = (Char) 0xff)
{
BJump = 1;
}
Else
{
BJump = 0;
}
} While (bJump = 1 );

Close (rc );
}
}

Main (int argc, char * argv [])
{
Char strAdd [16];
Struct sockaddr_in sin;
Int port = 9998;
Int kk, ii;
Int forknum = 10, loopnum = 10;

System ("clear ");

Memset (strAdd, 0, 16 );
Memcpy (strAdd, "192.168.1.197", 13 );

Bzero (char *) & sin, sizeof (sin ));
Sin. sin_family = AF_INET;
Sin. sin_addr.s_addr = inet_addr (strAdd );
Sin. sin_port = htons (port );

If (argc> = 2) forknum = atoi (argv [1]);
If (argc> = 3) loopnum = atoi (argv [2]);

For (kk = 1; kk <= forknum; kk ++)
{
Printf ("kk: % d \ n", kk );
If (fork () = 0)
{
Workthread (sin, loopnum );
Exit (0 );
}
}
Return;
}


The source code for the server to process Client requests is as follows:

# Include

Extern CT MainCt;
Extern int errno;
Pthread_cond_t tcn_th_cond = PTHREAD_COND_INITIALIZER;
Pthread_key_t p_key; // not used
Struct tcn_thread_mgr * tcn_th_mgr = NULL;

Int TreadClntrequest (struct tcn_thread_data * data)
{
Int socket;
BYTE RecvRecMessage [HOSTMSGLEN + 1];
Int nRet;

// Socket = pthread_getspecific (p_key );
Socket = data-> sock;

Memset (RecvRecMessage, 0, MSGLEN + 1 );

LogMessage ("run TreadClntrequest: socket = % d", socket );
NRet = recv (socket, RecvRecMessage, sizeof (CLIENTPKG), 0 );
If (nRet! = Sizeof (CLIENTPKG ))
{
LogMessage ("recv error! Errno = % d, errMsg: % s. ", errno, strerror (errno ));
}
Else
{
RecvRecMessage [6] = (char) 0xFF;
SendDataToClient (socket, RecvRecMessage, MAINPACK, MainCt. TraceData );
}

Close (socket );
LogMessage ("TreadClntrequest finish! ");

Return EXECOK;
}

// All signals are blocked during thread execution.
Void thread_signal_init ()
{
Sigset_t thread_sigmask;
Int rc;

If (rc = sigfillset (& thread_sigmask )))
{
Pthread_exit (NULL );
}

If (rc = pthread_sigmask (SIG_BLOCK, & thread_sigmask, NULL )))
{
Pthread_exit (NULL );
}
}

Void * apctclnt_thread_run (void * args)
{
LogMessage ("run apctclnt_thread_run ");
Struct tcn_thread_data * data = (struct tcn_thread_data *) args;
Thread_signal_init ();

// Pthread_setspecific (p_key, args );

Data-> thread_id = pthread_self ();
TreadClntrequest (data );

Pthread_mutex_lock (& (tcn_th_mgr-> lock ));
If (tcn_th_mgr-> num_active_threads> = tcn_th_mgr-> max_threads)
{
LogMessage ("call pthread_cond_signal ");
Pthread_cond_signal (& tcn_th_cond );
}

Tcn_th_mgr-> num_active_threads --;

Data-> thread_id = THREAD_NULL;
Pthread_mutex_unlock (& (tcn_th_mgr-> lock ));

LogMessage ("apctclnt_thread_run thread exit! ");
Pthread_exit (NULL );

Return NULL;
}

Int acptclnt_thread_create (int socket)
{
Int rc;
Pthread_t pTreateClnt;
Pthread_attr_t;
Int stacksize;
Int thread_num;

Stacksize = 1024;

Pthread_attr_init (& );
Pthread_attr_setdetachstate (& a, PTHREAD_CREATE_DETACHED); // PTHREAD _ CREATE_JOINABLE
Pthread_attr_setstacksize (& a, stacksize );

LogMessage ("acptclnt_thread_create socket = % d", socket );

Pthread_mutex_lock (& tcn_th_mgr-> lock );

While (tcn_th_mgr-> num_active_threads> = tcn_th_mgr-> max_threads)
{
LogMessage ("call pthread_cond_wait ");
Pthread_cond_wait (& tcn_th_cond, & tcn_th_mgr-> lock );
}

/* Search for an open slot to store the thread data in */
For (thread_num = 0; thread_num <tcn_th_mgr-> max_threads; thread_num ++)
{
If (tcn_th_mgr-> thread_data [thread_num]. thread_id = THREAD_NULL)
Break;
}

Tcn_th_mgr-> thread_data [thread_num]. sock = socket;

Rc = pthread_create (& tcn_th_mgr-> thread_data [thread_num]. thread_id,
& A, apctclnt_thread_run, (void *) (& (tcn_th_mgr-> thread_data [thread_num]);
// Rc = pthread_create (& pTreateClnt, & a, apctclnt_thread_run, (void *) socket );
If (rc! = 0)
{
LogMessage ("AcptClnt: create thread fail! Rc = % d, errMsg: % s. ", rc, strerror (rc ));
Close (socket );
}
Else
{
LogMessage ("create thread: apctclnt_thread_run OK .");
Tcn_th_mgr-> num_active_threads ++;
}

Pthread_mutex_unlock (& tcn_th_mgr-> lock );

Pthread_attr_destroy (& );

Return EXECOK;
}

Struct sigaction acptclnt_sa_int;

Void acptclnt_signal_chld (int signal)
{
Int stat;
LogMessage ("do acptclnt_signal_chld ");

Wait3 (NULL, WNOHANG, NULL );
/* While (waitpid (-1, & stat, WNOHANG)> 0)
{
LogMessage ("have kill a child ");
}
*/
Return;
}

Int acptclnt_threads_init ()
{
Pthread_key_create (& p_key, NULL );
Tcn_th_mgr = calloc (1, sizeof (struct tcn_thread_mgr ));
If (tcn_th_mgr = NULL)
{
Return EXECFAIL;
}
Else
{
Tcn_th_mgr-> max_threads = MainCt. MaxThreadNum;
Tcn_th_mgr-> thread_data = calloc (tcn_th_mgr-> max_threads, sizeof (struct tcn_thread_data ));
If (tcn_th_mgr-> thread_data = NULL)
{
Free (tcn_th_mgr );
Return EXECFAIL;
}

Pthread_mutex_init (& tcn_th_mgr-> lock, NULL );
Tcn_th_mgr-> num_active_threads = 0;
}
Return EXECOK;
}

Void acptclnt_destroy ()
{
If (tcn_th_mgr)
{
Pthread_mutex_destroy (& tcn_th_mgr-> lock );

If (tcn_th_mgr-> thread_data)
Free (tcn_th_mgr-> thread_data );

Free (tcn_th_mgr );
}
}

Int acptclnt_signal_init ()
{
Sigset_t sigmask;

Sigemptyset (& sigmask );
If (sigaddset (& sigmask, SIGCHLD ))
{
LogMessage ("sigaddset: % s", strerror (errno ));
Return EXECFAIL;
}

If (pthread_sigmask (SIG_UNBLOCK, & sigmask, NULL ))
{
LogMessage ("Setting thread signal mask: % s", strerror (errno ));
Return EXECFAIL;
}

Acptclnt_sa_int.sa_handler = acptclnt_signal_chld;
If (sigaction (SIGCHLD, & acptclnt_sa_int, NULL ))
{
LogMessage ("signal SIGCHLD not registered: % s", strerror (errno ));
Return EXECFAIL;
}

Return EXECOK;
}

/*
Function: receives the processing program.
*/
Void * AcptClnt ()
{
Struct sockaddr_in rstLclAddr;
Struct sockaddr_in tcp_addr;
Int wAddrLen;
Socklen_t clilen;
Int sockfd, accsockfd;


If (acptclnt_threads_init ()! = EXECOK)
{
Pthread_exit (NULL );
}

If (acptclnt_signal_init ()! = EXECOK)
{
Acptclnt_destroy ();
Pthread_exit (NULL );
}

WAddrLen = sizeof (rstLclAddr );
Sockfd = socket (AF_INET, SOCK_STREAM, 0 );
If (sockfd <0)
{
LogMessage ("AcptClnt: Create Socket error! Errno = % d, errMsg: % s. ", errno, strerror (errno ));
Acptclnt_destroy ();
Pthread_exit (NULL );
}
Else
{
LogMessage ("AcptClnt: Create Socket OK! Socket = % d ", sockfd );
}

RstLclAddr. sin_family = AF_INET; // "Internet" Address Family
RstLclAddr. sin_addr.s_addr = inet_addr (MainCt. HostAddr); // Local IP address
RstLclAddr. sin_port = htons (MainCt. ClientPort); // Set to "Echo" Port
If (bind (sockfd, (struct sockaddr *) & rstLclAddr, wAddrLen) <0)
{
LogMessage ("AcptClnt: Socket Bind error! IP: % s, Port: % d. errno = % d, errMsg: % s .",\
MainCt. HostAddr, MainCt. ClientPort, errno, strerror (errno ));
Acptclnt_destroy ();
Pthread_exit (NULL );
}

If (listen (FIG, 100) <0)
{
LogMessage ("AcptClnt: Socket Listen error! Errno = % d, errMsg: % s. ", errno, strerror (errno ));
Acptclnt_destroy ();
Pthread_exit (NULL );
}

LogMessage ("AcptClnt Progress: Start Success! ");

For (;;)
{
Accsockfd = accept (sockfd, (struct sockaddr *) & tcp_addr, & clilen );
If (accsockfd <0)
{
LogMessage ("AcptClnt: Socket Accept failed! Errno = % d, errMsg: % s. ", errno, strerror (errno ));
}
Else
{
LogMessage ("AcptClnt: Accepted Client_Request... socket = % d", accsockfd );
Acptclnt_thread_create (accsockfd );
}
Continue;
}
}
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.