Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

two ways voice chat using recvfrom() sendto() not working probably...

Posted on 2011-03-20
20
Medium Priority
?
553 Views
Last Modified: 2012-05-11
Hi,
I have the following code for two ways chat using UDP, recvfrom() and sendto() in sys/socket.h but for some reason my client can only talk but not listen and my server can only listen but not talk can someone take a look at the code please.

I did use pthread, and check it's validity using printing messages and I think my mutex being applied right as well, I fiind it weird that both my server and client have pretty much the same code except that one of them wait for connection as a server while the other establish the connection(not much of establishing considering im using UDP) any ideas what's wrong with my mechanism?


thanks,
             
////////////////////////SERVER////////////////

#include	"voip.h"
#include <pthread.h>
#include <fcntl.h>

int  			sockfd;
	struct sockaddr_in	serv_sock, cli_sock;
	char                    packet[PACKETSIZE];
	int fd,num, sum=0;

char *message1 = "this is thread two, being tested with recieving as thread";

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
int recvalue = 0;
///////////////////////prototype//////////////

void *writespeaker();
void *print_message(void *ptr);
void *readmic();

////////////////////////////////////////////


int
main(int argc, char **argv)
{
	
	
	/* Open  a UDP SOCKET */
	
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}
	
	fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read
	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

       	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	puts("Audio Device is setup"); 	

	/* Set the socket parameters */
	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family      = AF_INET;
	serv_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_sock.sin_port        = htons(SERV_PORT);
 
	if (bind(sockfd,  &serv_sock, sizeof(serv_sock))<0)
	  perror(" Failed in binding the Server sock!");
   


pthread_t thread1,thread2;

pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);


pthread_join(thread1,NULL);
pthread_join(thread2,NULL);


}


int Transmitter(int sockfd, struct sockaddr_in *serv_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockfd, packet, read_size, 0, serv_sock, servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *cli_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, cli_sock, &len );
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

void Playback( char *packet, int write_size)
{
  write(devfd, packet, PACKETSIZE);	
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    fprintf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);printf( "\n condition met\n");
}

void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
pthread_mutex_lock(&count_mutex);
recvalue = Receiver(sockfd, &cli_sock, packet, write_size, sizeof(cli_sock));
if(recvalue == 0)	        
{		
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{

pthread_cond_signal(&condition_var); //signal to release the mutex
}


pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{

for(;;)
{
read_size = read (devfd, packet, PACKETSIZE);
pthread_mutex_lock(&count_mutex);
pthread_cond_wait(&condition_var,&count_mutex);
//printf( "\n condition met holla!\n");
num = Transmitter(sockfd, &serv_sock, packet, read_size, sizeof(serv_sock));
if(num > 0)
{	
 write(fd, packet, PACKETSIZE);	
}
pthread_mutex_unlock(&count_mutex);
}

		
}

Open in new window

////////////////CLIENT//////////////////////

#include "voip.h"
#include <pthread.h>
#include <fcntl.h>

	int  sockfd;
	struct sockaddr_in  serv_sock, cli_sock;
	socklen_t len;
	char hostname[MAXHOSTNAMELEN];
	char packet[PACKETSIZE];
	int fd, num, sum=0;
	int recvalue = 0;

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
///////////////////////prototype//////////////

void *writespeaker();
void *readmic();

////////////////////////////////////////////


int main(int argc, char **argv )
{
		 
	if ( argc != 3){
	  puts("Usage: Name Server Port");
	  exit(0);
	}

	/* Get the Server Parameters from the input*/  
	serv_addr.name = argv[1];
	serv_addr.port = atoi(argv[2]);
	
	printf(" Serv_addr is %s Serv_port is %d\n", serv_addr.name, serv_addr.port);

	
	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	  puts("Audio Device is setup");
	
	/* Get the Client Parameters */
        if ( gethostname(hostname, MAXHOSTNAMELEN) <0 )
	  perror("Couldn't get the hostname!");
        
	printf("hostname is %s\n",hostname);

	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family = AF_INET;
	serv_sock.sin_port = htons(serv_addr.port);
	inet_pton(AF_INET, serv_addr.name, &serv_sock.sin_addr);
 
    	/* Open  a UDP SOCKET - This is the only SOCKET opened in Daemon Server */
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	 exit(1);
	}
	fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read
        

pthread_t thread1,thread2;

pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);


pthread_join(thread1,NULL);
pthread_join(thread2,NULL);


}

int Transmitter(int sockfd, struct sockaddr_in *serv_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockfd, packet, read_size, 0, serv_sock, servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *cli_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, cli_sock, &len );
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    printf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);
}
void Playback( char *packet, int write_size)
{

  write(devfd, packet, PACKETSIZE);	
}



void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
pthread_mutex_lock(&count_mutex);

recvalue = Receiver(sockfd, &cli_sock, packet, write_size, sizeof(cli_sock));
if(recvalue == 0)	        
{		
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{
//printf("\n it is -1 now \n");

pthread_cond_signal(&condition_var); //signal to release the mutex
}

pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{

for(;;)
{
read_size = read (devfd, packet, PACKETSIZE);
pthread_mutex_lock(&count_mutex);
pthread_cond_wait(&condition_var,&count_mutex);
printf( "\n condition met holla!\n");
num = Transmitter(sockfd, &serv_sock, packet, read_size, sizeof(serv_sock));
if(num > 0)
{	
 write(fd, packet, PACKETSIZE);	
}
pthread_mutex_unlock(&count_mutex);
}
 
		
}

Open in new window

/////////////////////header/////////////////
/* Header File */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h> 
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>		/* for strerror */
#include <errno.h>		/* for errno */


#define PACKETSIZE  512
#define MAXHOSTNAMELEN  32
#define SERV_PORT 12000

/* Define the Server's Hostname and UDP port number */
 struct SERV_INFO {
          char *name;              
          int  port;               
 } ;

 struct SERV_INFO  cli_addr, serv_addr;  

 struct Audio_Para {
    int speed;
    int stereo;
    int PCM;
 } ; 
 
 struct Audio_Para  audio_paras;

int SetupAudio( char *devicename, struct Audio_Para *audio_paras);
int Transmitter(int sockfd, struct sockaddr_in *serv_sock, char *packet,int read_size, socklen_t servlen);
int Receiver(int sockfd, struct sockaddr_in *cli_addr, char *packet, int write_size, socklen_t clilen);
void Playback( char *packet, int write_size);

int   devfd, read_size, write_size;
char *devicename = "/dev/audio";

Open in new window

0
Comment
Question by:logicallayer
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 4
  • +2
20 Comments
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 200 total points
ID: 35179961
in case of udp you have connection-less sockets where youself need to do all synchronisation. that means some packets may come in wrong order or got lost and you must get aware of that and have code to handle that accordingly. also you need to handle the case where a new client connects to the server differently from following communication to that client. also if you make the socket non-blocking you would get error for almost any call to recvfrom and you have to handle the would-block errors differently from real errors.

in your code i couldn't detect any of these considerations though i may not have analysed it thoroughly enough.

i generally have a different design for tasks like yours. i firstly have a 'normal' tcpip connection where a server listens to a socket in order to accept new clients. if a client connected i open two more sockets (and threads to handle them), one is tcpip and one is udp. the udp now is for fast transfer and the tcpip is for lost packets or other hand-shake things.

Sara
0
 
LVL 12

Expert Comment

by:trinitrotoluene
ID: 35186182
take a look at this sample application here

http://www.codeproject.com/KB/IP/client_server_socket.aspx
0
 
LVL 12

Expert Comment

by:trinitrotoluene
ID: 35186187
it uses WinSock though, but you should be able to extend it to Unix as well
0
Create the perfect environment for any meeting

You might have a modern environment with all sorts of high-tech equipment, but what makes it worthwhile is how you seamlessly bring together the presentation with audio, video and lighting. The ATEN Control System provides integrated control and system automation.

 

Author Comment

by:logicallayer
ID: 35186426
thanks everyone for the comments, here is where I'm at right now.

ok I found out that my problem is that my server isn't establishing a connection to the client which is has to be done by extracting the IP address of the UDP packet and then use it with proper port number (let's say I know it in advance) to send packets to the client side....


so my question how can I extract the ip address of a upd packet being received and then use that IP address to send data back to the client...

all I could find on the net is by using IP_PKTINFO inside setpacketopt()

but I couldn't figure out how to use it to extract the IP address of the header...

any ideas?
0
 

Author Comment

by:logicallayer
ID: 35186428
thanks everyone for the comments, here is where I'm at right now.

ok I found out that my problem is that my server isn't establishing a connection to the client which is has to be done by extracting the IP address of the UDP packet and then use it with proper port number (let's say I know it in advance) to send packets to the client side....


so my question how can I extract the ip address of a upd packet being received and then use that IP address to send data back to the client...

all I could find on the net is by using IP_PKTINFO inside setpacketopt()

but I couldn't figure out how to use it to extract the IP address of the header...

any ideas?

regard the link I prefer not use winsock, but thanks it's a neat article
0
 
LVL 35

Expert Comment

by:sarabande
ID: 35187095
as told the udp is a connectionless socket communication. you ask for service which is part of a tcpip connection. here the tcpip would provide information about sender, number of packages, and more and would guarantee that packages were transfered in the right order without losses. all that is missing when using udp and you would need to put the information into the packages yourself and establish mechanism to reorder packages, to request lost packages and so on.

by the way, winsock and linux sockets are nearly same beside of few exceptions which easily can be handled, for example error constants.

Sara
0
 
LVL 35

Expert Comment

by:Duncan Roe
ID: 35187619
I wouldn't worry about out_of_sequence packets it's really quite rare and wouldn't be especially  serious even if it did happen.
I think you have to have a bit of a rethink regarding your design. What is the difference between a server and a client? Can the server handle multiple conversations? If not, they are peers and should both run the same code.
Also I really dislike "polling" - I very strongly recommend you use select() or poll() (ironic name poll() - it doesn't mean try every interval but instead is an alternative multi-channel interface to select()). You need one function to handle all socket transactions. If you want to write something, add your socket to the list of entities wanting to write. If you want to read something, add your socket to the list of entities wanting to read. In either case, select() or poll() will tell you when you can go ahead - there's no need to be non-blocking.
Sticking with select() (with which I'm slightly more familiar although I've used both), you are faced with the problem of how do you wake up select() when you have a new item to write ?
Luckily there's an easy solution. You open a loopback Tcp socket and write a byte to it, thus waking the select(). In previous projects I have only written a zero byte, but I can see future applications where the value of the byte might be nonzero and have some special meaning (like go and check a queue somewhere for,say, freshly completed connection requests).
0
 
LVL 35

Expert Comment

by:sarabande
ID: 35187758
lost or disordered udp packages might be a rare thing especially on one machine but if they happen they would lead to unacceptable errors in most cases. you may think of a simple file transfer where a wrong or missing package would spoil the whole file at the receiver side. generally udp is not recommended for wan or for lan's which have more than one router.
 
if you want the ip address of the sender when using udp socket you need to pass the ip address with the message.

Sara
0
 
LVL 35

Expert Comment

by:Duncan Roe
ID: 35188000
With audio though, there would be some garbled sound then you'd carry on. Although on first reading the Q I did think that sound usually went over some other protocol, the name of which escapes me for no
0
 
LVL 35

Expert Comment

by:Duncan Roe
ID: 35188060
Actually the possibility of mis-ordered packets is a complete irrelevancy at this stage. The problem is no communication at all in one direction - that is what we need to address
0
 
LVL 35

Expert Comment

by:sarabande
ID: 35188249
it is not irrelevant cause udp is the wrong decision in my opinion. also communication works - if i understood the author's last post correctly - and the last q. was 'how to gain ip address of sender when using udp' .

Sara
0
 
LVL 35

Accepted Solution

by:
Duncan Roe earned 1400 total points
ID: 35189553
Easy - the man page says
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
Here one should supply a pointer to a struct sockaddr_in cast to a pointer to struct_sockaddr with addrlen being sizeof the preceding argument. On receipt of a datagram,  src_addr is filled in to be the source of the datagram - a responding sendto() should give that as its dest_addr.

See man 2 recvfrom and man 2 sendto
0
 
LVL 32

Assisted Solution

by:phoffric
phoffric earned 400 total points
ID: 35190511
>> if you want the ip address of the sender when using udp socket you need to pass the ip address with the message
   Assuming UDP over IPv4, then that is being done implicitly. Image taken from
       http://learn-networking.com/tcp-ip/how-the-internet-layer-works

>> On receipt of a datagram,  src_addr is filled in to be the source of the datagram
So, src_addr should be the the value of the circled item in the image.
IP-Packet.PNG
0
 

Author Comment

by:logicallayer
ID: 35195588
I really appreciate everyone effort on this, you guys helping me alot going through this

sarabande,
thanks for your insight , regard using tcp instead of udp I have to say I don't agree with you for the following reason
first we know that udp does have less over head which quite important in video and audio streaming
second what's the probabilty of error in coaxial cable, I think 10^-9 , considering losing a packet or two you would still make out of what you are hearing as you are missng with a spectrum level, well it's digital but still...i prefer to work on the problem before I try to find a room for improvement but thanks though

duncane and  phoffric this exaclty what I'm looking for, I made adjustment to the code can you please check it out to see I'm passing the value of my pointer correctly, I think I'm missing it up some how but your suggestion totatally make sense, I almost gave up and was going to try to open a new socket to pass the ip address of the client then use it on the server to connect back to the client but you guys saved me quite some work


my problem i n my code is with first how to pass the ip is it as pointer or reference, I'm not really sure
and second how to assign a port to that ip address which is of type stuct sockaddr_in, I tried something here you can check in the code but I have a feeling it's not the way to  do it

      




//here is the part of trying to assign ip address

//here we are assigning the socket information for the client (that is going to be transmitted to)
	ip_sock = *cli_sock;	
	//bzero(&ip_sock, sizeof(ip_sock));
	ip_sock.sin_family = AF_INET;
	ip_sock.sin_port = htons(12001);

//we bind it (although we are sending so it might be not neccssary)	
if (bind(sockmd,  &ip_sock, sizeof(ip_sock))<0)
	  perror(" Failed in binding the Server sock!");

Open in new window

recv.c
connect.c
voip.h
0
 
LVL 35

Expert Comment

by:Duncan Roe
ID: 35202495
Why is bzero commented out? You want INADDR_ANY (zero) if doing a bind. bzero (or memset) would achieve that.
0
 

Author Comment

by:logicallayer
ID: 35203240
actually I decided to not bother with getting the ip of the client but instead make the two programs identical except each one is listening on a different port, the only problem I'm facing now is that I'm getting echo sound that stays in there and doesn't stop, I have tried different methods but all failed, do you mind taking one more look please

the other frustrating thing that might be behind the problem is
my read_size = read(devfd, packet, PACKETSIZE); always returning size
while I thought by calling the following function, it should return -1 when there is no DATA to be read
fcntl(devfd,F_SETFL,O_NONBLOCK);

actually it did return -1 at some point in my code, then I did something that took that away... do you think that you can put your hands on it?

I really appreciate your help as my head is spinning...

#include	"voip.h"
#include <pthread.h>
#include <fcntl.h>

int  			sockfd,sockmd;
	struct sockaddr_in	serv_sock, cli_sock,ip_sock;
	char                    packet[PACKETSIZE];
	int fd,devfd2,num, sum=0;

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
int recvalue = 0;
///////////////////////prototype//////////////

void *writespeaker();
void *readmic();

////////////////////////////////////////////


int main(int argc, char **argv)
{
	
	/* Open  a UDP SOCKET */
	
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}

if ((sockmd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}	
	
	//fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read


//make it no blocking to return error
	fcntl(sockmd,F_SETFL,O_NONBLOCK);
	fcntl(devfd,F_SETFL,O_NONBLOCK);	


	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

       	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	puts("Audio Device is setup"); 	


	/* Set the socket parameters for the recieving*/
	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family      = AF_INET;
	serv_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_sock.sin_port        = htons(SERV_PORT);
 
	if (bind(sockfd,  &serv_sock, sizeof(serv_sock))<0)
	  perror(" Failed in binding the Server sock!");




/* Get the Server Parameters from the input*/  

	cli_addr.name = argv[1];
	cli_addr.port = atoi(argv[2]);

bzero(&cli_sock, sizeof(cli_sock));
	cli_sock.sin_family = AF_INET;
	cli_sock.sin_port = htons(cli_addr.port);
	inet_pton(AF_INET, cli_addr.name, &cli_sock.sin_addr);




 

	

pthread_t thread1,thread2;

pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);

pthread_join(thread1,NULL);
pthread_join(thread2,NULL);

}


int Transmitter(int sockmd, struct sockaddr_in *cli_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockmd, packet, read_size, 0, cli_sock,servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *serv_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, serv_sock, &len ); //cli_sock length was &len changed to sizeof(cli_sock)
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

void Playback( char *packet, int write_size)
{
  write(devfd, packet, PACKETSIZE);	
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
	
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    fprintf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);printf( "\n condition met\n");
}



void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
//pthread_mutex_lock(&count_mutex);
//printf("reciver GOT NOTHING");
recvalue = Receiver(sockfd, &serv_sock, packet, write_size, sizeof(serv_sock));
if(recvalue == 0)	        
{		
printf("reciver GOT SOMETHING!!!!!!");
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{
//pthread_cond_signal(&condition_var); //signal to release the mutex
}


//pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{
for(;;)
{

//pthread_cond_wait(&condition_var,&count_mutex);
//pthread_mutex_lock(&count_mutex);
//printf("before cond");
//wait here until the writespeaker signal to continue

//printf("after cond");
read_size = read(devfd, packet, PACKETSIZE);
printf("\n read size is: %d",read_size);
if(read_size > 0)
{
printf( "\n condition met holla!\n");

num = Transmitter(sockmd, &cli_sock, packet, read_size, sizeof(cli_sock));
//if(num > 0)
//{	
// write(fd, packet, PACKETSIZE);	
//}
//pthread_mutex_unlock(&count_mutex);
}		
}
}

Open in new window

#include	"voip.h"
#include <pthread.h>
#include <fcntl.h>

int  			sockfd,sockmd;
	struct sockaddr_in	serv_sock, cli_sock,ip_sock;
	char                    packet[PACKETSIZE];
	int fd,devfd2,num, sum=0;

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
int recvalue = 0;
///////////////////////prototype//////////////

void *writespeaker();
void *readmic();

////////////////////////////////////////////


int main(int argc, char **argv)
{
	
	/* Open  a UDP SOCKET */
	
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}

if ((sockmd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("Socket()");
	  exit(1);
	}	
	
	//fcntl(sockfd,F_SETFL,O_NONBLOCK); //make it non-blocking so it returns an error if no message to be read


//make it no blocking to return error
	fcntl(sockmd,F_SETFL,O_NONBLOCK);
	fcntl(devfd,F_SETFL,O_NONBLOCK);	


	/* Set some params */
	audio_paras.speed = 8000;
	audio_paras.stereo = 0;
	audio_paras.PCM  = AFMT_U8; 

       	if (SetupAudio(devicename, &audio_paras)!=0) {
	    perror("Error in Initializing Audio Device!");
	    exit(-1);
	}
	else 
	puts("Audio Device is setup"); 	


	/* Set the socket parameters for the recieving*/
	bzero(&serv_sock, sizeof(serv_sock));
	serv_sock.sin_family      = AF_INET;
	serv_sock.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_sock.sin_port        = htons(12001);
 
	if (bind(sockfd,  &serv_sock, sizeof(serv_sock))<0)
	  perror(" Failed in binding the Server sock!");



/* Get the Server Parameters from the input*/  

	cli_addr.name = argv[1];
	cli_addr.port = atoi(argv[2]);

bzero(&cli_sock, sizeof(cli_sock));
	cli_sock.sin_family = AF_INET;
	cli_sock.sin_port = htons(cli_addr.port);
	inet_pton(AF_INET, cli_addr.name, &cli_sock.sin_addr);



	

pthread_t thread1,thread2;



pthread_create(&thread1,NULL, writespeaker,NULL);
pthread_create(&thread2,NULL, readmic,NULL);

pthread_join(thread1,NULL);
pthread_join(thread2,NULL);

}


int Transmitter(int sockmd, struct sockaddr_in *cli_sock, char *packet,int read_size, socklen_t servlen)
{
  int n;
  n = sendto(sockmd, packet, read_size, 0, cli_sock,servlen);
  //printf("%d ",n);
  return(n);
}

int Receiver(int sockfd, struct sockaddr_in *serv_sock, char *packet, int write_size, socklen_t clilen)
{
  int len;
  len = clilen;
  /* Here using polling to avoid too block - 10ms is good? */
  write_size = recvfrom(sockfd, packet, PACKETSIZE, 0, serv_sock, &len ); //cli_sock length was &len changed to sizeof(cli_sock)
  //printf("write_size is %d\n",write_size);
  if (write_size > 0)
     return(0);
  else
     return (-1);
}

void Playback( char *packet, int write_size)
{
  write(devfd, packet, PACKETSIZE);	
}

int SetupAudio( char *devicename, struct Audio_Para *audio_paras)
{
    int format  = AFMT_QUERY;  
    printf("%s\n",devicename);
    devfd=-1;
	
    /* Open /dev/audio */
    if((devfd = open(devicename, O_RDWR)) < 0) {
	if(errno == EBUSY) {
	    fprintf(stderr, "%s in use\n", devicename);
	}
	printf(stderr, "%s: %s\n", devicename, strerror(errno));
	return(-1);
    }

    /* Set the format PCM: 8 unsigned bits */
    if((ioctl(devfd, SNDCTL_DSP_SETFMT, &audio_paras->PCM)) < 0) {
	perror("SNDCTL_DSP_GETFMTS");
	return(-1);
    }

    if((ioctl(devfd, SNDCTL_DSP_GETFMTS, &format)) < 0) {
      perror("SNDCTL");
      return(-1);
    }

    /* Set the number of channels */
    if((ioctl(devfd, SNDCTL_DSP_STEREO, &audio_paras->stereo)) < 0) {
	perror("SNDCTL_DSP_STEREO");
	return(-1);
    }
    printf("\tSet %s mode\n", (audio_paras->stereo) ? "STEREO" : "MONO");

    /* Set the sample speed */
    if((ioctl(devfd, SNDCTL_DSP_SPEED, &audio_paras->speed)) < 0) {
	perror("SNDCTL_DSP_SPEED");
	return(-1);
    }
    printf("\tSPEED %d Hz\n", audio_paras->speed);

    return(0);printf( "\n condition met\n");
}



void *writespeaker()
{

//pay attention that pthread mutex examole website uses one function only in both threads,
//here we have two functions that are trying to access the same variable
//we shouldn't allow one function to access the variable unless the other function is done with it
//notice we are talking about sockfd in receiver() and transmitter() 	

for(;;)
{
//pthread_mutex_lock(&count_mutex);
//printf("reciver GOT NOTHING");
recvalue = Receiver(sockfd, &serv_sock, packet, write_size, sizeof(serv_sock));
if(recvalue == 0)	        
{		
printf("reciver GOT SOMETHING!!!!!!");
		 Playback( packet, write_size);
}
else if(recvalue == -1)
{
//pthread_cond_signal(&condition_var); //signal to release the mutex
}


//pthread_mutex_unlock(&count_mutex);
}
}

void *readmic()
{
for(;;)
{

//pthread_cond_wait(&condition_var,&count_mutex);
//pthread_mutex_lock(&count_mutex);
printf("before cond");
//wait here until the writespeaker signal to continue

//printf("after cond");
read_size = read(devfd, packet, PACKETSIZE);
printf("\n read size is: %d",read_size);
if(read_size > 0)
{
printf( "\n condition met holla!\n");

num = Transmitter(sockmd, &cli_sock, packet, read_size, sizeof(cli_sock));
//if(num > 0)
//{	
// write(fd, packet, PACKETSIZE);	
//}
//pthread_mutex_unlock(&count_mutex);
}		
}
}

Open in new window

0
 

Author Comment

by:logicallayer
ID: 35203553
for the problem of fcntl(devfd,F_SETFL,O_NONBLOCK); not working I found out my mistake was I had this function before I initialize the value of devfd and open the file so I fixed this now it's non-blocking but still when the peer1 take peer2 hear echo on the voice, what I noticed it seems that peer2 transmitting the packet back to peer1 and peer1 doing the same (indefinitely)

I figured that using one headset one plug on the mic of peer1 and the earphone on the plug of peer2 then once I talk and hear echo I switch the earphone to peer1 and I still hear the echo...so that does prove the retransmition indefinitely but why?
0
 
LVL 32

Expert Comment

by:phoffric
ID: 35204155
I'm not able to run this app, but I just wonder whether you have the echo and oscillation problem if you test on two platforms and two headsets (that are not near each other).
0
 

Author Comment

by:logicallayer
ID: 35204251
Im testing with one headset that earphone are not loud one connected to one pc mic and the other to the earphone on the other pc, I think my problem has to do with either devfd which only open one file for read and write but im not sure how read and write exactly behave, also I suspect using the same variable for read and write which is int packet, athough I tried to change this variable but it didnt fix the problem
0
 

Author Closing Comment

by:logicallayer
ID: 35209592
nevermind , I found out that using only one headest seems that it created some polarity that cause the echo, I brought two headset and there is no echo, which is great


thanks everyone,
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
I have seen several blogs and forum entries elsewhere state that because NTFS volumes do not support linux ownership or permissions, they cannot be used for anonymous ftp upload through the vsftpd program.   IT can be done and here's how to get i…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question