full duplex communication between server & client - c

I want to make a code for full duplex communication between server & client using this code.
I got error in receive-message thread from server side & in send-message thread from client side.
please help me to solve this errors & suggest me if any other changes are required.
Thanks :)
server.cpp
int newsockfd, n;
void error(const char *msg)
{
perror(msg);
exit(1);
}
void* recvFn( void* data )
{
char buffer[256];
while(n==0){
memset( buffer, sizeof(buffer), 0);
n = recv(newsockfd,buffer,255,MSG_PEEK);
if(n>0){
printf("cliet: ");
printf("%s",buffer);
}
}
return NULL;
}
void* sendFn( void* data )
{
char temp[255], buffer[255];
while(n==0){
memset( buffer, sizeof(buffer), 0);
fgets(temp,255,stdin);
sprintf(buffer,"clent: %s",temp);
n = send(newsockfd,buffer,strlen(buffer),MSG_EOR);
}
return NULL;
}
int main(int argc, char *argv[])
{
int sockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
pthread_t recvThread, sendThread;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
memset( &serv_addr, sizeof(serv_addr), 0);
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
int on = 1;
if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof( on ) ) != 0 ) {
close( sockfd );
return -1;
}
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
n = 0;
int rc;
rc = pthread_create( &recvThread, NULL, recvFn, NULL);
if(rc){
printf("error in receive-message thread\n");
return -1;
}
rc = pthread_create( &sendThread, NULL, sendFn, NULL);
if(rc){
printf("error in send-message thread\n");
return -1;
}
close(newsockfd);
close(sockfd);
pthread_cancel(recvThread);
pthread_cancel(sendThread);
return 0;
}
client.cpp
int sockfd, n;
void* recvFn( void* data )
{
char buffer[255];
while( n==0 ){
memset( buffer, sizeof(buffer), 0);
n = recv(sockfd,buffer,255,MSG_PEEK);
if(n>0){
printf("server: ");
printf("%s",buffer);
}
}
return NULL;
}
void* sendFn( void* data )
{
char temp[255], buffer[255];
while( n==0 ){
memset( buffer, sizeof(buffer), 0);
fgets(temp,255,stdin);
sprintf(buffer,"clent: %s",temp);
n = send(sockfd,buffer,strlen(buffer),MSG_EOR);
}
return NULL;
}
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int portno;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
pthread_t recvThread, sendThread;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
portno = atoi(argv[2]);
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset( &serv_addr, sizeof(serv_addr), 0);
serv_addr.sin_family = AF_INET;
memcpy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on connecting");
n = 0;
int rc;
rc = pthread_create( &sendThread, NULL, sendFn, NULL);
if(rc){
printf("error in send-message thread\n");
return -1;
}
rc = pthread_create( &recvThread, NULL, recvFn, NULL);
if(rc){
printf("error in receive-message thread\n");
return -1;
}
close(sockfd);
pthread_cancel(recvThread);
pthread_cancel(sendThread);
return 0;
}

Your pthread_mutex operations are completely pointless. You're referring only to local variables inside the mutex lock other than n, which should be local in each thread and newsockfd which also should not be global, see below. (Don't you think that a function which calls recv should have a local variable to capture the number of bytes read, and not share that silly little temporary variable globally with other threads?)
Your main thread is in a while loop, creating threads like crazy. Also, inside that loop it has closed the one and only accepted socket, right after creating the threads.
You forgot to put your accept inside the loop, evidently.
Also you seem to think that the main loop will somehow wait for the pair of threads to terminate before launching new ones. You are missing pthread_join calls to wait for the threads finish communicating. If you want the thread to keep going while the main loop accepts new connections using new threads, you should make those threads detached with pthread_detached or using a thread-creation attribute which makes them detached. Non-detached threads which are not pthread_join-ed continue to occupy resources.
Speaking of shutdown, is it really the correct condition that the threads keep looping while n == 0? As soon as n is set to nonzero by one of the threads, the shutdown condition is met. But a nonzero value is normal: some bytes written or read. Your reader should terminate the loop when there is a fatal receive error on the socket, or the read returns zero.
Also, you are evaluating n == 0 outside of the mutex!
If you want to accept multiple concurrent connections, each with its pair of threads, then you cannot use a single global socket. You have to give each pair of threads their own socket. The two threads within each pair do not have to use a mutex to share the socket. The socket calls are thread-safe in the kernel and the threads are not both doing reads or writes; one is reading and one is writing.
Other problems
Your sender keeps sending uninitialized garbage: a buffer that was never set to contain any data.
You have a bzero of 256 bytes on an array of 255 bytes.
Also
Don't use bzero (or bcopy, etc). It's a BSD-ism from the 1980's. The C language was finally standardized in 1989 by ANSI and soon after in 1990 by ISO. At that time, it already had the library functions memset, memcpy and memmove.
I think 22 years later, it is safe to retire bcopy, dontcha think?

Related

multi-process in C : global variable's value

Here is the code from a website. It used multi-processing to create a server. My question is: will the parent process close(newsockfd) executed before the child process doprocessing(newsockfd) ?
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
===-=================
void doprocessing (int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
==========-==========================
code is from this website:
http://www.tutorialspoint.com/unix_sockets/socket_server_example.htm
When the process is forked, the gets a copy of the open set of file desriptors, and the reference count on the open filess is incremented accordingly. The close only happens in the parent process, so the child still maintains a reference to the open file. The order of execution doesn't really matter. On a multi-cpu system, it may happen truly simultaneously.
Global variables are not shared by forked child processes. A forked process runs in its own virtual memory space.

Multithreaded Server in LInux

I am Working on server Programming in C in Linux environment.At same time there might be several clients linked with the Server.It's my first project on server Programming and not having much experience in Multi-threading.Till Now i have Programmed following for Multithreading.
I want to get some idea about following Points.
1.How many clients will the server Handle?
2.will pthread_t thr;create multiple Threads or i need to do something like pthread_t thr[X] to create X Threads ?
3.How can i get the data for each client in the following code ?
4.Will pthread_create create a new copy of *connection_handler for each new client connected.
void dieWithError(char *errormsg);
FILE *file;
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size;
char *message , client_message[2000];
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
//end of string marker
client_message[read_size] = '\0';
printf("%s",client_message);
fprintf(file,"%s", client_message);
//clear the message buffer
memset(client_message, 0, 2000);
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
return 0;
}
int main(int argc, char** argv) {
int sock_desc = 0, connfd = 0,listenfd =0;
struct sockaddr_in serv_addr;
int clntSock;
struct sockaddr_in echoClntAddr;
unsigned int clntLen;
char sendBuff[1025];
char recvBuff[10025];
int n = 0;
pthread_t thr;
sock_desc = socket(AF_INET, SOCK_STREAM, 0);
if(sock_desc < 0 )
dieWithError("Unable to open Socket\n");
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET ;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(7024);
if(bind(sock_desc, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
dieWithError("bind failed\n");
if(listen(sock_desc,3) < 0)
dieWithError("listen failed\n");
file = fopen("testServer.txt", "w");
clntSock = sizeof(struct sockaddr);
int i =0;
while((connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,(socklen_t*)&clntSock)))
{
puts("Connection accepted");
if( pthread_create( &thr, NULL , connection_handler , (void*) &connfd) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( thread_id , NULL);
puts("Handler assigned");
}
if (connfd < 0)
{
perror("accept failed");
return 1;
}
return (EXIT_SUCCESS);
}
void dieWithError(char *errormsg){
printf("%s", errormsg);
}
It depends on the server machine, and how many threads it can handle. Generally speaking, the more threads you have, the more time the operating system will spend just switching between threads meaning the threads themselves will have less time doing any real work.
E.g. pthread_t thr; is a single variable, able to hold a single thread. You can reuse it for multiple threads, but then you loose the other threads leading to a resource leak. You probably need an array or a list if you want multiple threads.
Structures. One structure per thread, each structure containing the thread information (pthread_t), the client socket, and everything else needed by both the main thread and the client-handling thread.
No. connection_handler is a function, there will only be one instance of a function per process in memory, functions are not copied.

threaded server in c

I did not found an answer to my question before, nor did i know if that has an specific name for what i want to do, basically i have a program that runs a simulation, with graphical interface and calculations in the background, and i want to control it through commands with a tcp basic server/client but this means that i have to incorporate the server function inside the controlling function, so i made my server inside a thread and i am running something in the main function, while i call the server function in a thread just for testing, but i cannot send anything to the server, my client application does not get a response, and the server does not receive anything... the code is messy because i am testing a lot of stuff in it, and the identation is messy too...
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
int test= 0;
void threadServer(){
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, c;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while(c){
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr,
&clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
exit(1);
}
/* If connection is established then start communicating */
bzero(buffer,256);
n = read( newsockfd,buffer,255 );
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
//if(buffer[0]==t){
//c=0;
//exit(1);
//}else{
//c=1;
//}
printf("Here is the message: %s\n",buffer);
/* Write a response to the client */
n = write(newsockfd,"I got your message",18);
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
test =1;
}
//return 0;
}
void main(){
pthread_t threads[1];
int rc;
long t;
char k;
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, threadServer, (void *)t);
if(rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
while(1){
printf("type any key:\n");
scanf("%c",&k);
printf("you typed %c\n", k);
printf("testing server thread : %d\n", test);
}
/* Last thing that main() should do */
pthread_exit(NULL);
}

String with thread in tcp client / server in C

I'm trying to develop an application in C to receive a message and send it in TCP. For that, I'm using a 2 threads : the server thread to listen and a client thread to send it.
Here the server and the main function :
void dostuff(int sock)
{
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
else {
pthread_t t_tcp_client;
pthread_create(&t_tcp_client, NULL, tcp_client, buffer);
}
n = write(sock,"Message received",18);
if (n < 0) error("ERROR writing to socket");
}
static void *tcp_server(void *p_data)
{
int sockfd, newsockfd, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(TCP_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) error("ERROR on accept");
pid = fork();
if (pid < 0) error("ERROR on fork");
if (pid == 0) {
close(sockfd);
dostuff(newsockfd);
exit(0);
} else {
close(newsockfd);
}
}
close(sockfd);
return 0;
}
int main (void)
{
pthread_t t_tcp_server;
pthread_create(&t_tcp_server, NULL, tcp_server, NULL);
pthread_join(t_tcp_server, NULL);
return 0;
}
And the client thread :
static void *tcp_client(void *p_data)
{
if (p_data != NULL)
{
char const *message = p_data;
printf("Message transmitted : %s\n", message);
}
return 0;
}
The problem is that the client thread doesn't receive the good char, the result is :
Message transmitted : ???~?
I think the problem comes from the line : n = read(sock,buffer,255); but I don't really understand why.
Thank you for your help
static char buffer[256];
void dostuff(int sock)
{
int n;
bzero(buffer,256);
n = read(sock,buffer,255);
...
}
Be careful when using sockets, one read may don't give you the totality of the message you wait.
In case of structured messages, the protocol you define (you should define it well) have to give a message identifier at first, and you read until you receive sizeof( theSpecificMessage ), theSpecificMessage is identified by the identifier.
do_stuff most likely exited before the client thread did it's work.
The client thread uses stack allocated memory which then had been freed when do_stuff exited, and will be reused by some other code.
A solution to this would be to pass heap allocated memory to the client. If allocated dynamically the latter then needs to be freed by the client after it has done its work.

Thread-specific data

I have a client program as follows and I need to make it multithreaded i.e one thread per connection. But the variable sockfd is to be kept global to one thread. I understand to do this I need to use pthread_key_t, pthread_key_create...etc. But, I am confused how to use it. I would be gratefull for any help.
int sockfd;
pthread_key_t key_to_sockfd;
void error(const char *msg)
{
perror(msg);
exit(0);
}
void set_connection(char *argv[])
{
int portno;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
return;
}
void send_message()
{
char buffer[256];
int i=0,n;
do{
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
i++;
}while(i<3);
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
return;
}
void disconnect()
{
close(sockfd);
return;
}
void client_thrd(char *argv[])
{
set_connection(argv);
send_message();
disconnect();
}
int main(int argc, char *argv[])
{
pthread_t thid[2];
int i;
void *status;
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
for(i=0;i<1;i++)
pthread_create(&thid[i],NULL,(void*)&client_thrd,(void*)argv);
for(i=0;i<1;i++)
pthread_join(thid[i],&status);
return 0;
}
I have executed the program for one thread and works fine. But as I increase the number of threads to more then one ofcourse it does not work because of the global vaiable sockfd. This is a test program for something much larger.
Thanks and Regards
It is very easy to use. You call pthread_key_create(&key_to_sockfd, NULL) at the start of your program then in each thread you will see an initial value of NULL. Use the function pthread_setspecific(key_to_sockfd, <pointer to a struct which contains sockfd>) in each thread.
From then on each thread will see a different pointer to the structure that contains your sockfd. When your thread is done with it, you delete the structure and use pthread_setspecific(key_to_sockfd, NULL)
When the threads are finished you call pthread_key_delete(key_to_sockfd) to remove the storage. You can also automatically cleanup by providing a callback function to pthread_key_create to free up the memory when the thread has finished.
From what I see you don't need a global variable to achieve what you want to do. Create a "state" data structure and initialize it for each thread before launching it. The void* parameter in the thread interface is made for this.
If I look to your code you overwrite with each thread you start the socket descriptor sockfd. So each thread will make a new connection and gets a new sockfd. With this code you have the good possibility one thread is closing the connection of another thread. If you want to use for each thread its own socket descriptor why don't you use a pointer to share the same socket descriptor within the same thread?
void client_thrd(char *argv[])
{
int sockfd;
set_connection(&sockfd, argv);
send_message(&sockfd);
disconnect(&sockfd);
}

Resources