Cannot transfer a wave-file over a socket?!?

Started by
17 comments, last by trondb 21 years, 4 months ago
OK heres my source-code for the client side:

#include <windows.h> // for winsock functions
#include <stdio.h> // for printf()
#include <string.h> // for strcopy()
#include <stdlib.h> // for atoi() and other helpfunctions
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <Dmusici.h>
#include "dxutil.h"
#include
#include
#include
using namespace std;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEFINITIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define domainAF AF_INET // Address Family = Internet
#define protocol 0 // set to 0 to use default protocol for chosen domain and type

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int TCPSocket, // ID for socket to communicate through
UDPSocket;
struct hostent *remoteInfo; // temp storage for IP
struct sockaddr_in remoteAddress; // stores address info for remote
int addressLength;
struct in_addr remoteIP; // IP address for remote

bool listening;
char *nickName;
int READBUFFERSIZE;
int HEADERSIZE;
int j; // used for clearing out strings
ofstream audioCache("audiocache.wav",ios::out|ios::binary|ios::ate);
HWND hWndAudio;
IDirectMusicLoader8 *pLoader = NULL;
IDirectMusicPerformance8 *pPerformance = NULL;
IDirectMusicSegment8 *pSound = NULL;
bool TCPMODE;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION PROTOTYPES
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void connectTo ( const char*, const int );
void getAudio ( void );
HRESULT hrInitDirectAudio ( HWND );
HRESULT hrLoadSound ( char* );
HRESULT hrPlaySound ( IDirectMusicSegment8* );
void vShutdownDirectAudio ( void );

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CONNECT TO SERVER
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void connectTo(const char *remoteName, const int remotePort){
char *programInfo; // 1024 with zero fill, msgformat from server
char *headerData; // 128 with zero fill, msgformat from server
char *choice; // 1 for TCPMODE, 2 for UDPMODE

// Attempt to create a socket for communication
if ((TCPSocket = socket(domainAF, SOCK_STREAM, protocol)) < 0){
printf("*** System unable to create TCP socket ***\n");
exit(1);
}
if ((UDPSocket = socket(domainAF, SOCK_DGRAM, protocol)) < 0){
printf("*** System unable to create UDP socket ***\n");
exit(1);
}

// Attempt to lookup IP address for remote
remoteInfo = gethostbyname(remoteName);
if (remoteInfo == NULL){
printf("*** Could not get remote IP ***\n");
exit(1);
} else memcpy(&remoteIP, remoteInfo->h_addr, 4);

// Fill in data about remote address
remoteAddress.sin_family = domainAF;
remoteAddress.sin_port = htons(remotePort); // convert 16-bit values between host and network byte order
remoteAddress.sin_addr.s_addr = inet_addr(inet_ntoa(remoteIP));

choice = new char[1];
choice[0] = 0;
printf("Select 1 : TCP MODE\n 2 : UDP MODE : ");
scanf ("%s", choice); // read userid from keyboard into userID
if(!strcmp(choice,"1")){
printf(" TCPMODE Enabled\n");
TCPMODE = true;
}
else if(!strcmp(choice,"2")){
printf(" UDPMODE Enabled\n");
TCPMODE = false;
}
else{printf("*** ILLEGAL CHOICE ***"); exit(1);}

printf ("Nickname : ");
nickName = new char[30];
for(j=0; j<30; j++)
{
nickName[j] = 0;
}
scanf ("%s", nickName); // read userid from keyboard into userID

// Initiate connection-oriented communication ( blocking call connect() )
if ( connect( TCPSocket, (struct sockaddr *)&remoteAddress, sizeof(remoteAddress) ) != 0){
printf("*** System unable to connect - no TCP server ***\n");
exit(1);
}
printf("\n");
printf("-=Radio %s=- at %s, port %d\n", remoteName, inet_ntoa(remoteIP), remotePort);

send( TCPSocket, nickName, 30, 0 ); // sends outbuffer to server using TCP
send( TCPSocket, choice, 1, 0 );
programInfo = new char[READBUFFERSIZE+1]; for(j=0; j headerData = new char[HEADERSIZE+1]; for(j=0; j recv( TCPSocket, programInfo, READBUFFERSIZE, 0 );
recv( TCPSocket, headerData, HEADERSIZE, 0 );
//printf("RECEIVED HEADERDATA: %s\n",headerData);
printf("%s\n",programInfo);
char inBuffer[20];
char outBuffer[20];
strcpy(outBuffer,"OK");
memset ( inBuffer, ''\0'', sizeof(inBuffer) ); //clears out inbuffer before use
addressLength = sizeof(remoteAddress);
sendto( UDPSocket, outBuffer, 19, 0,
(struct sockaddr *)&remoteAddress, addressLength ); // sends outbuffer to server using UDP
recvfrom( UDPSocket, inBuffer, 19, 0,
(struct sockaddr *)&remoteAddress, &addressLength);

// Receive headerinfo for wavefile
audioCache.write(headerData,HEADERSIZE);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// INIT AUDIOSYSTEM USING DIRECTX
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT hrInitDirectAudio(HWND hWnd){
HRESULT hResult;
IDirectMusicAudioPath8 *path;

// Init COM - all DirectAudio functions are COM-based
CoInitialize(NULL);

// Create Loader-interface, store it in pLoader
hResult = CoCreateInstance( CLSID_DirectMusicLoader,
NULL,
CLSCTX_INPROC,
IID_IDirectMusicLoader8,
(void**)&pLoader );
if (FAILED(hResult)){ printf("*** DX8 Cant create Loader\n"); return(NULL);}

// Create Performance-interface, store it in pPerformance
hResult = CoCreateInstance( CLSID_DirectMusicPerformance,
NULL,
CLSCTX_INPROC,
IID_IDirectMusicPerformance8,
(void**)&pPerformance );
if (FAILED(hResult)){ printf("*** DX8 Cant create Performance\n"); return(NULL);}

// Initalize Audio in the performance interface
hResult = pPerformance->InitAudio( NULL, // NULL=internal IDirectMusic8 interface created
NULL, // NULL=internal IDirectSound8 interface created
hWnd, // Handle to Window using this sound-system
DMUS_APATH_DYNAMIC_STEREO, // Type of default path
4, // # Performance-channels
DMUS_AUDIOF_ALL, // This flag includes all flags:
// * DMUS_AUDIOF_STREAMING - allows streaming WAVE files!
// * DMUS_AUDIOF_BUFFERS - use multiple buffers
// * DMUS_AUDIOF_ENVIRON - use environmental modeling
// * DMUS_AUDIOF_EAX - use EAX effects
// * DMUS_AUDIOF_3D - allow 3D buffers
NULL ); // Default DMUS_AUDIOPARAM structure used
if (FAILED(hResult)){ printf("*** DX8 Cant init audio\n"); return(NULL);}

// Retrieve default audio path - used for playing sounds
if (FAILED( pPerformance->GetDefaultAudioPath(&path))){ printf("*** DX8 Cant get default audio-path\n"); return(NULL);}

// Set default volume for the playback-path
if (FAILED( path->SetVolume(0, // Volume 0 = full volume, in the range [0..-9600]
0) // Duration in milliseconds for volume-change. 0 = immediate.
)){ printf("*** DX8 Cant set path volume\n"); return(NULL);}
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LOAD SOUND WAVE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT hrLoadSound( char *szFileName){
WCHAR wstrFileName[256];
DXUtil_ConvertGenericStringToWide( wstrFileName, szFileName ); // Unicode conversion

// Check if DSound is Initialized OK
if ( !pLoader || !pPerformance ){ printf("*** DX8 not initialized\n"); return(NULL);}

// Clean up sound if it already exists
if ( pSound ){
pSound->Unload( pPerformance );
pSound->Release();
pSound = NULL;
}

// Load sound resource from file and place it in segment
if (FAILED( pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment, // Object-type to load
IID_IDirectMusicSegment8, // Interface ID
wstrFileName, // Filename for sound-file
(LPVOID*) &pSound // Stores loaded object
))){ printf("*** DX8 Cant load file\n"); return(NULL);}
// Download the data - transfer it to performance interface that play sounds
if (FAILED( pSound->Download( pPerformance))){ printf("*** DX8 Cant download file\n"); return(NULL); }
return(S_OK);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PLAYSOUND WAVE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT hrPlaySound(IDirectMusicSegment8 *pSegment){
// Check if DSound is Initialized OK
if ( !pSegment || !pPerformance ){ printf("*** DX8 not initialized\n"); return(NULL);}

// Play segment
if(FAILED( pPerformance->PlaySegmentEx(
pSegment, // Segment-source to play
NULL, // Segment-name - not implemented in DX8
NULL, // Transition-object to associate with playback
DMUS_SEGF_DEFAULT | DMUS_SEGF_SECONDARY, // Flags! Secondary buffer can play several simultaneously
0, // Starttime 0 - starts playing sound immediately
NULL, // IDirectMusicSegmentState8 state pointer for playback
NULL, // audiopath/segmentstate to stop when this segment starts playing
NULL // Audiopath. NULL = default.
))){ printf("*** DX8 Cant playback soundfile\n"); return(NULL); }
return(S_OK);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CLEAN UP DIRECTAUDIO
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void vShutdownDirectAudio( void ){
if ( pLoader ){
pLoader->Release();
pLoader = NULL;
}
if ( pPerformance ){
pPerformance->Release();
pPerformance = NULL;
}
if ( pSound ){
pSound->Unload( pPerformance ); // Required for all downloaded segments into performance objects
pSound->Release();
pSound = NULL;
}
CoUninitialize();
}

void closeConnection( void ){
closesocket(TCPSocket);
closesocket(UDPSocket);
WSACleanup();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GET AUDIO STREAM
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Should run in own thread
void getAudio( void ){
char *soundData; // 128 with zero fill, msgformat from server
int audioBytesRead,
totalBytesRead,
chunksRead;
listening = true;
printf("Receiving broadcast sound-data\n[");
chunksRead = totalBytesRead = 0;
while (listening==true){
soundData = new char[READBUFFERSIZE+1];
for(j=0; j {
soundData[j] = 0;
}
if(TCPMODE) audioBytesRead = recv( TCPSocket, soundData, READBUFFERSIZE, 0 );
else audioBytesRead = recvfrom( UDPSocket, soundData, READBUFFERSIZE, 0,
(struct sockaddr *)&remoteAddress, &addressLength);
totalBytesRead += audioBytesRead;
//if (audioBytesRead > 0){
//if(TCPMODE) printf("t"); else printf("u");
if( soundData[0] == ''E''){ // Server sends message containing "EOP" when radio-program is finished
if( soundData[1] == ''O''){
if( soundData[2] == ''P''){
//printf("\n%s - Shutting Down\n",soundData);
listening = false;
}
}
}
else{
chunksRead++;
// Append wave-data to file
audioCache.write(soundData,READBUFFERSIZE);
}
// Play sounddata after caching enough data

//}
}
printf("] %d chunks read.\n",chunksRead);
audioCache.close();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MAIN
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]){
WORD wVersionRequested = MAKEWORD(1,1);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
char temp[1];
printf("\n<<< Winsock Radio Stream Client >>>\n (C) 2002 Trond Borg\n\n");
hrInitDirectAudio(hWndAudio);
READBUFFERSIZE = 128;
HEADERSIZE = 128;
if (argc != 3){
connectTo("z8n", 888);
}
else connectTo( argv[1], atoi(argv[2]) );
getAudio();
closeConnection();
printf("Audio broadcast finished\n");
hrLoadSound("audiocache.wav");
hrPlaySound(pSound);
vShutdownDirectAudio();
scanf ("%s",temp);
return(1);
}//END MAIN

"That''s Tron. He fights for the users."
"That's Tron. He fights for the users."
Advertisement
...and heres the server-code:
(THANKS AGAIN ALL)
#include // for printf()
#include // for atoi() and other helpfunctions
#include // for socket functions
#include //
#include // for generating timestamp time()
#include //
#include //
#include //
#include // for strncopy() etc
#include //
#include //
#include //
#include //
using namespace std; ///
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define DOMAIN_AF AF_INET // Address Family = Internet
#define PROTOCOL 0 // set to 0 to use default protocol for chosen domain and type
#define MAXQUEUE 3 // Max 3 pending connections
#define MAXCLIENTS 3 //
#define SENDBUFFERSIZE 128 ///
#define HEADERSIZE 128 ////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct broadcast{
char *headerData;
long headerSize;
char *audioData;
long byteSize,
bytesSent,
bytesLeft;
char *programInfo; // Text string sent to clients logging on to the show, info about the wav being broadcasted
bool done; // Indicates that all data has been broadcasted
};

struct client{
char *nickName;
struct sockaddr_in address; // stores address info for remote
struct hostent *Info; // temp storage for retreiving IP
struct in_addr IP; // IP address for remote
int addressLength;
int socket_fd;
bool connected;
bool TCPMODE; // True for TCP, false for UDP

};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct broadcast broadCast; //
struct waveChunk waveData[]; //
u_short servePort;
struct client clients[MAXCLIENTS];// Stores all clients in an array
int numberOfClients; //
int numberOfChunks; //
FILE *logFile; // filepointer for logging broadcasts and listeners
timeval timeout; //
//
struct sockaddr_in localAddress; // stores address info for remote
struct hostent *localInfo; // temp storage for retreiving IP
struct in_addr localIP; // IP address for remote
char *localHostName; // Name for server
int j; // used for clearing out strings
int TCPSocket; // ID for socket to listen on for requests and send TCP traffic
int UDPSocket; // ID for socket for UDP traffic
bool running; // Indicates server is on
bool TCPMODE; // True for TCP, false for UDP
bool OVRMODE; // Whether to override clients request for individual modes
bool TCPMODE_SET; // Contains TCPMODE if OVRMODE set, otherwise contains clients.TCPMODE
ifstream waveFile("radio.wav",ios::in|ios::binary|ios::ate); //
//ofstream tempFile("verify.wav",ios::out|ios::binary|ios::ate);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNTION PROTOTYPES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loadWave ( void ); // Loads wavefile and fills out the struct with header data + prepares buffer
void updateProgramInfo ( void ); // Adds timestamp + info to struct for wavefile
void initServer ( void ); // Starts server
bool checkForNewClients ( void ); // Checks for new listener
void disconnectClient ( int ); // Removes a listener
void sendProgramInfo ( int ); // Sends info about the program to the new listener
void getMessage ( int ); // Receive message from clients
void broadcastAudio ( void ); // Sends next part of the radioprogram to the listener

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LOAD WAVE FILE
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loadWave( void ){
broadCast.headerSize = HEADERSIZE;
broadCast.byteSize = waveFile.tellg() - broadCast.headerSize;
waveFile.seekg(0, ios::beg);
broadCast.headerData = new char[broadCast.headerSize];
for(j=0; j {
broadCast.headerData[j] = 0;
}
waveFile.read(broadCast.headerData, broadCast.headerSize);
printf("Buffering %d bytes of headerdata\n",broadCast.headerSize);
//tempFile.write(broadCast.headerData, broadCast.headerSize); // Used for local verification purposes
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// STORE TIMESTAMP + PROGRAM INFO
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void updateProgramInfo( void ){
SYSTEMTIME timer;
char temp[1024]; // used for misc stringmanipulation
char timeClk[25];
char date[25];
char *timeStamp; // puts timedata in string
// Store broadcast-start timestamp in broadCast.programInfo and log-file
strcpy(temp, "Station up at ");
GetLocalTime(&timer); // gets local time from system
GetDateFormat(0,DATE_SHORTDATE,&timer,NULL,date,sizeof(date));
GetTimeFormat(0,LOCALE_NOUSEROVERRIDE,&timer,NULL,timeClk,sizeof(timeClk));
timeStamp = date; strcat( timeStamp, " at "); strcat( timeStamp, timeClk);
strcat(temp, timeStamp); strcat(temp,"\n");
logFile = fopen("radiolog.log", "a"); //Open or create file for both reading and appending
fprintf(logFile,temp); // stores string as a line in the log-file
broadCast.programInfo = new char[SENDBUFFERSIZE];
for(j=0; j {
broadCast.programInfo[j] = 0;
}
strcpy( broadCast.programInfo, temp ); // Appends timestamp to broadCast.programInfo
printf("%s",broadCast.programInfo);
broadCast.done = false;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// START SERVER FOR BROADCASTING
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initServer( void ){
// Create a socket for requests
if ((TCPSocket = socket(DOMAIN_AF, SOCK_STREAM, PROTOCOL)) < 0){
printf("*** System unable to create TCP listeningsocket ***\n");
exit(1);
}
if ((UDPSocket = socket(DOMAIN_AF, SOCK_DGRAM, PROTOCOL)) < 0){
printf("*** System unable to create UDP listeningsocket ***\n");
exit(1);
}

// Fill in addressinfo for local socket
localHostName = new char[80];
for(j=0; j<80; j++)
{
localHostName[j] = 0;
}
gethostname( localHostName, sizeof(localHostName) );
localInfo = gethostbyname(localHostName);
if (localInfo == NULL){
printf("*** Could not get IP ***\n");
exit(1);
} else memcpy(&localIP, localInfo->h_addr, 4);
localAddress.sin_family = DOMAIN_AF;
localAddress.sin_port = htons(servePort); // convert 16-bit values between host and network byte order
localAddress.sin_addr.s_addr = INADDR_ANY;

// Bind socket to address
if( bind( TCPSocket, (struct sockaddr *)&localAddress, sizeof(localAddress) ) <0 ){
printf("*** System unable to bind TCP socket ***\n");
exit(1);
}
if( bind( UDPSocket, (struct sockaddr *)&localAddress, sizeof(localAddress) ) <0 ){
printf("*** System unable to bind UDP socket ***\n");
exit(1);
}
printf("Radio %s on %s:%d\n\n",localHostName, inet_ntoa(localIP), servePort);
listen( TCPSocket, MAXQUEUE ); // Listen for connectionrequests
for (int i=0; i .connected = false;<br>}//END INITSERVER<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// CHECK FOR NEW LISTENERS REQUESTING TO LISTEN TO THE RADIO<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// Returns true if connection is made, false if no connections attempted or no free radioslots<br>bool checkForNewClients( void ){<br> int selectResult; // data returned from the select function<br> int nfds; // New filedescriptor to allow multiple connectionrequests<br> fd_set conn; // read variable for select function<br><br> timeout.tv_sec = 0; // set to 0 for Non Blocking<br> timeout.tv_usec = 0;<br><br> if (numberOfClients < MAXCLIENTS)<br> {<br> FD_ZERO (&conn); <br> FD_SET (TCPSocket, &conn); // conn get the data from the listeningsocket<br> nfds = TCPSocket + 1; // Up by &#111;ne - shouldnt be the same for each client connecting<br><br> selectResult = select(nfds, &conn, NULL, NULL, &timeout); // Check if any data is coming in…<br><br> if (selectResult > 0) // Someone is trying to Connect<br> {<br> int i = 0;<br> char *clientMode;<br> char temp[1024];<br><br> while(clients.connected == true && i < MAXCLIENTS){<br> i++;<br> }<br> if (clients.connected == true) return false; // All slots full<br><br> clients.addressLength = sizeof(clients.address);<br> clients.socket_fd = accept(TCPSocket,<br> (struct sockaddr *)&clients.address,<br> &clients.addressLength);<br> // Client Connected<br> numberOfClients++;<br> clients.connected = true;<br> memcpy( &clients.IP, &clients.address.sin_addr.s_addr, 4 ); // Gets IP for client<br> clients.nickName = new char[31];<br> for(j=0; j<31; j++)<br> {<br> clients.nickName[j] = 0;<br> }<br> clientMode = new char[2]; //receivebuffer = expected databytes +1 for stringterminator<br> clientMode[0] = clientMode[1] = 0;<br> recv( clients.socket_fd, clients.nickName, 30, 0 );<br> recv( clients.socket_fd, clientMode, 1, 0 );<br> if (clientMode[0] == ''1'') clients.TCPMODE = true; else clients.TCPMODE = false;<br> strcpy( temp, clients.nickName); <br> strcat( temp, "("); <br> strcat( temp, inet_ntoa(clients.IP));<br> strcat( temp, ")");<br> memset ( clients.nickName, ''\0'', sizeof(clients.nickName) ); // Clears out inbuffer before use<br> strcpy(clients.nickName,temp);<br> printf("\n* * * %s tuned in at slot %d requesting ",clients.nickName,i);<br> if (clients.TCPMODE == true) printf("TCPMODE\n"); else printf("UDPMODE\n");<br> fprintf(logFile,"Tuned in ");<br> fprintf(logFile,clients.nickName); // stores string as a line in the log-file<br> fprintf(logFile,"\n");<br> <br> sendProgramInfo(i);<br><br> char inBuffer[20];<br> char outBuffer[20];<br> strcpy(outBuffer,"OK");<br> memset ( inBuffer, ''\0'', sizeof(inBuffer) ); //clears out inbuffer before use<br> recvfrom( UDPSocket, inBuffer, 19, 0, <br> (struct sockaddr *)&clients.address, &clients.addressLength);<br> sendto(UDPSocket, outBuffer, 19, 0,<br> (struct sockaddr *)&clients.address, clients.addressLength);<br> } else return false; // No connection attempts at this time<br> }<br> return true; // Connected a new client<br>}<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// SEND PROGRAM INFO TO NEW LISTENER<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>void sendProgramInfo(int i){<br> send(clients.socket_fd, broadCast.programInfo, SENDBUFFERSIZE, 0 );<br> send(clients.socket_fd, broadCast.headerData, HEADERSIZE, 0 );<br>}<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// SEND THE AUDIOSTREAM TO ALL LISTENERS<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>void broadcastAudio( void ){<br> int prevNoListeners = 0;<br> int bytesToSend = SENDBUFFERSIZE;<br> int chunkNo = 0;<br> char *sendBuffer;<br> <br> // Send chunks<br> broadCast.bytesLeft = broadCast.byteSize;<br> broadCast.bytesSent = 0;<br> <br> while(broadCast.done == false){<br> // wait for a couple of MS so the receiver can process in the speed being sent…<br> Sleep(10);<br> chunkNo++; // Keep count of how many chunks are being sent<br> // Prepare sendbuffer and how many bytes to send<br> if (broadCast.bytesLeft < SENDBUFFERSIZE){<br> bytesToSend = broadCast.bytesLeft;<br> broadCast.done = true;<br> }<br> broadCast.bytesLeft -= bytesToSend;<br> broadCast.bytesSent += bytesToSend;<br> sendBuffer = new char[bytesToSend];<br> for(j=0; j<bytesToSend; j++) sendBuffer[j] = 0; // Clear out the sendBuffer<br> waveFile.read(sendBuffer, bytesToSend); // Put next chunk of audiostream into sendBuffer<br> //tempFile.write(sendBuffer, bytesToSend); // Used for local verification<br><br> // If more listeners have tuned in, print a little message to screen<br> if (prevNoListeners != numberOfClients) printf("Sending to %d listener(s): ",numberOfClients);<br> prevNoListeners = numberOfClients;<br> for (int i=0; i<MAXCLIENTS; i++){<br> if (clients.connected){<br> if (OVRMODE) TCPMODE_SET = TCPMODE; else TCPMODE_SET = clients.TCPMODE;<br> if (TCPMODE_SET) send(clients.socket_fd, sendBuffer, bytesToSend,0);<br> else sendto(UDPSocket, sendBuffer, bytesToSend, 0,<br> (struct sockaddr *)&clients.address, clients.addressLength);<br> //if (TCPMODE_SET) printf("t"); else printf("u"); <br> }<br> }<br> if (broadCast.bytesSent == broadCast.byteSize) broadCast.done = true;<br> else checkForNewClients();<br> }<br> printf("\n%d chunks DONE\n",chunkNo);<br> waveFile.close();<br> //tempFile.close();<br> printf("\nSending EOP to slot(s): ");<br> for (int i=0; i<MAXCLIENTS; i++){<br> char *terminate;<br> terminate = new char[4];<br> strcpy(terminate,"EOP");<br> terminate[4] = 0;<br> if (clients.connected){<br> printf("%d.",i);<br> if (OVRMODE) TCPMODE_SET = TCPMODE; else TCPMODE_SET = clients.TCPMODE;<br> if (TCPMODE_SET) send(clients.socket_fd, terminate, bytesToSend, 0 );<br> else {printf(".");<br> sendto(UDPSocket, terminate, bytesToSend, 0,<br> (struct sockaddr *)&clients.address, clients.addressLength);<br> }<br> }<br> }<br> printf("\n");<br>}<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// CHECK FOR INCOMING CLIENT-MESSAGES<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>void checkForMessages()<br>{<br> fd_set input_set, <br> exc_set; // Input and Error sets for the select function<br> int selectResult, // This is Used for the Select command to store the value it gets back<br> nfds; // New filedescriptor to allow multiple connectionrequests<br> timeout.tv_sec = 0; // 0 for non-blocking<br> timeout.tv_usec = 0;<br> nfds = 0;<br> FD_ZERO(&input_set); // Set up the input,and exception sets for select().<br> FD_ZERO(&exc_set);<br> <br> for (int i = 0; i < MAXCLIENTS<img src="wink.gif" width=15 height=15 align=middle> // Add all connected sockets to set for checking<br> {<br> if (clients.connected == true){<br> FD_SET(clients.socket_fd,&input_set);<br> FD_SET(clients.socket_fd,&exc_set);<br> }<br> nfds++;<br> i++;<br> }<br> selectResult = select(nfds,&input_set,NULL,&exc_set,&timeout); // Checks for incoming<br> if (selectResult > 0)<br> {<br> for (int i=0; i < numberOfClients<img src="wink.gif" width=15 height=15 align=middle> //Look through all the clients to see which &#111;ne is giving error or data<br> {<br> if (FD_ISSET(clients.socket_fd,&exc_set)) // Error &#111;n socket<br> {<br> // Assume error means disconnection<br> printf("*%s disconnected from slot %d\n",clients.nickName,i);<br> disconnectClient(i);<br> }<br><br> if ((FD_ISSET(clients.socket_fd, &input_set))) // Incoming message<br> {<br> // Get whatever message the client sending, and carry out appropriate response<br> getMessage(i);<br> }<br> i++; // Next Client<br> }<br> }<br>}<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// PROCESS CLIENT-MESSAGES<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// (not used in this program, but included for later versions, if any)<br>// Get the message, and see what it is.<br>void getMessage(int i){<br> // Receive The Data and Put into a Buffer Until we know what it is.<br> char *rcvBuffer;<br> rcvBuffer = new char[2]; //receivebuffer = expected databytes +1 for stringterminator<br> rcvBuffer[0] = rcvBuffer[1] = 0;<br> if (OVRMODE) TCPMODE_SET = TCPMODE; else TCPMODE_SET = clients.TCPMODE;<br> if (TCPMODE_SET) recv(clients.socket_fd,rcvBuffer,1,0);<br> else recvfrom( UDPSocket, rcvBuffer, 1, 0, (struct sockaddr *)&clients.address, &clients.addressLength);<br> switch (rcvBuffer[0])<br> {<br> case ''1'':<br> printf("*%s requested TCPMODE &#111;n slot %d\n",clients.nickName,i);<br> clients.TCPMODE = true;<br> break;<br> case ''2'':<br> printf("*%s requested UDPMODE &#111;n slot %d\n",clients.nickName,i);<br> clients.TCPMODE = false;<br> break;<br> case ''3'':<br> printf("*%s stopped listening &#111;n slot %d\n",clients.nickName,i);<br> disconnectClient(i); <br> break;<br> }<br>}<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// DISCONNECT A LISTENER<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>void disconnectClient(int i){<br> closesocket(clients.socket_fd);<br> clients.connected = false;<br> numberOfClients–;<br>}<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// SHUTDOWN THE ENTIRE SERVER<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>void shutdownServer( void ){<br> closesocket(TCPSocket);<br> closesocket(UDPSocket);<br> for (int i = 0; i < MAXCLIENTS, i++<img src="wink.gif" width=15 height=15 align=middle><br> {<br> if (clients.connected) disconnectClient(i);<br> }<br> WSACleanup(); // Remove Winsock<br>}<br><br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>// MAIN<br>///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////<br>int main(int argc, char *argv[]){<br> WORD wVersionRequested = MAKEWORD(1, 1);<br> WSADATA wsaData;<br> WSAStartup(wVersionRequested, &wsaData);<br> char *choice;<br> running = true;<br> numberOfClients = 0;<br> printf("\n<<< Winsock TCP/UDP Radio Broadcaster >>>\n (C) 2002 Trond Borg\n\n");<br> choice = new char[1];<br> printf("Select 1 : CLIENT SELECT MODE\n");<br> printf(" 2 : TCP &#79;NLY MODE\n");<br> printf(" 3 : TCP &#79;NLY MODE : ");<br> scanf ("%s", choice); // read userid from keyboard into userID<br> if(!strcmp(choice,"1")){<br> OVRMODE = false;<br> }<br> if(!strcmp(choice,"2")){<br> TCPMODE = true;<br> OVRMODE = true;<br> }<br> if(!strcmp(choice,"3")){<br> TCPMODE = false;<br> OVRMODE = true;<br> }<br> if(OVRMODE){<br> if(TCPMODE) printf("TCP &#79;NLY MODE Enabled\n"); else printf("UDP &#79;NLY MODE Enabled\n");<br> }else printf(" CLIENT SELECT MODE Enabled\n");<br> <br> printf("\n");<br> loadWave();<br> updateProgramInfo();<br> if (argc < 2){<br> servePort = 888;<br> }<br> else servePort = atoi(argv[1]);<br> initServer();<br> //printf("Splitting wavedata into %d bit chunks for broadcasting\n",SENDBUFFERSIZE);<br> printf("Waiting for a listener before starting program\n");<br> while (numberOfClients == 0){<br> // wait a little or CPU-usage goes up to a 100%<br> // FIX <br> Sleep(1000);<br> checkForNewClients(); // Dont start radio until at least &#111;ne listener is ready<br> }<br> broadcastAudio(); // Send the audiofile chunk by chunk<br> shutdownServer(); // For all clients, close socket:<br> printf("Server closed down\n");<br> scanf ("%s",choice);<br> return(0);<br>}//END MAIN </i> <br><br>"That''s Tron. He fights for the users."
"That's Tron. He fights for the users."
I think I''ve found your error.

It appears that you are doing things slightly out-of-order.


  void getAudio( void ){    char  *soundData;	// 128 with zero fill, msgformat from server    int	   audioBytesRead,           totalBytesRead,	   chunksRead;    listening = true;    soundData = new char[READBUFFERSIZE];    printf("Receiving broadcast sound-data\n");    while (listening == true)    {	audioBytesRead = recv(local_socket_fd, soundData, READBUFFERSIZE, 0);	totalBytesRead += audioBytesRead;	if (audioBytesRead > 0)        {	    chunksRead++;	    // printf(".");	            if(soundData[0] == ''E'')            {                // Server sends message containing "EOP" when radio-program is finished	        // HUGE ASSUMPTION HERE.                if(soundData[1] == ''O'')                {					    if( soundData[2] == ''P'')                    {			printf("\n%s - Shutting Down\n",soundData);		                                listening = false;		    }		}	    }	    else            {		// Append wave-data to file                // changed READBUFFERSIZE to audioBytesRead                // you were potentially writing corrupt data.		audioCache.write(soundData, audioBytesRead);	    }	                // Play sounddata after caching enough data	}    }}  


See if that works. Other than that I''d have to spend more time with you code and unfortunately it isn''t that pretty to read Good luck.
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
BTW You are also making a huge assumption that the TCP/IP packets will arrive in discreet sizes.

Say the server sends:

send("12345678") 


and then:

send("EOP") 


But on the client you recv:

"12345678EOP"

Your code above doesn't know how to handle this. You should change your server code to send a packet length header. Like:

dataHeader.messageType   = DATA_MESSAGE;dataHeader.messageLength = bytesToSend;while(broadcast.done == false){    // more code    // ignoring byte ordering and packing    // send header    send(client,          (char*)&dataHeader,          sizeof(dataHeader.messageLength),         0);       // send data    send(client, data, bytesToSend, 0);      // more code} 


The server then sends an EOP_MESSAGE type when the end of the program has been reached:

dataHeader.messageType   = EOP_MESSAGE;dataHeader.messageLength = 0; 


This would allow your client to figure out how many bytes it needs to receive. This would also allow you to recognize when you receive an EOP.

If you need help with implementing this, let me know.

Regards.

[edited by - Digitalfiend on December 10, 2002 8:36:38 PM]
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
kool, I will try that out. Allthough I dont understand what I am doing out-of-order? The reason I put the
<> inside the loop was to clear it out between each send?

Can you explain why I dont need that? I am terrible with strings...



"That''s Tron. He fights for the users."
"That's Tron. He fights for the users."
sorry... I meant :
soundData = new char[READBUFFERSIZE+1];
within the while loop

"That''s Tron. He fights for the users."
"That's Tron. He fights for the users."
I think Digitalfiend deserves a pat on the back for being so helpful in this (and other) threads: pat pat...

trondb: if you are not so interested in learning the workings of sockets and just want to get the data across successfully you could use my sockets wrapper, it is easy to use and fully documented on my website, there is an example to show how to do a simple file transfer:
http://www.zppz.com/libraries/minisock/index.jsp
(runs on windows and linux)

Thanks zppz

BTW trondb, I made a litle bit of a goof in my pseudo-code above.

change:

send(client,     (char*)&dataHeader,     sizeof(dataHeader.messageLength)  ,     0); 


to

send(client,     (char*)&dataHeader,     sizeof(dataHeader)  ,     0); 


BTW Let me know if you are still having problems. I''ll whip up a small example for you when I get a chance.

Good luck.
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
Again, thanks alot Digitalfiend! It rocks to have people like you out there to help out when my skills don''t cut it!!! I am currently cramp-studying for my final exams, so I will have to implement this a little later in the week, but I''m sure its gonna work now!!! Thanks again (Y)

"That''s Tron. He fights for the users."
"That's Tron. He fights for the users."

This topic is closed to new replies.

Advertisement