⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 This a framework to test new ideas in transmission technology. Actual development is a LDPC-coder in
💻 C
字号:
/***************************************************************************           server.c  -  A channel server                            -------------------    begin                :  2002    authors              :  Linus Gasser    emails               :  linus.gasser@epfl.ch ***************************************************************************//***************************************************************************                                 Changes                                 ------- date - name - description 02-12-13 - ineiti - begin, ripped of from PLATON_2002 03-05-19 - ineiti - added support for multiple ports 03-11-27 - phil   - added group id for mimo  **************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************//** * A very simple server that allows multiple clients to connect and to * communicate through a fade-only channel. */#include <pthread.h>#include <sys/socket.h>#include <time.h>#include <netdb.h>#include <stdlib.h>#include <math.h>#include <sys/stat.h>#include <sys/types.h>#include "system.h"#include "channel_net.h"#include "antenna.h"#include "debugging.h"#include "server.h"#include "fading.h"#include "fading_multi.h"#include "fading_multi_complex.h"#include "flat.h"#include "command.h"#define DBG_LVL 0pthread_mutex_t mutex_rcv, mutex_send;pthread_cond_t cond_rcv, cond_send;struct client_params client[MAX_CLIENTS];double rx_gain[MAX_CLIENTS], tx_gain[MAX_CLIENTS];char tx_signal_buffer[MAX_CLIENTS][BLOCK_BUFFER+1][DAQ_DMA_BLOCK_SIZE_BYTES]__attribute__ ((aligned(8)));char rx_signal_buffer[MAX_CLIENTS][BLOCK_BUFFER+1][DAQ_DMA_BLOCK_SIZE_BYTES]__attribute__ ((aligned(8)));double channel_tap[MAX_CLIENTS+1][MAX_CLIENTS+1][CHANNEL_LENGTH];double complex channel_tap_cplx[MAX_CLIENTS+1][MAX_CLIENTS+1][CHANNEL_LENGTH];int nbr_ready_to_rcv, nbr_ready_to_send, nbr_clients, slot;int ready_to_rcv, ready_to_xmit, tx_block;int serving, got_rcv_mutex, is_complex,gid;/** * Handles the stream from/to one client. If a client drops the connection, * the thread ends. */static void * t_client(void * arg) {  int nbr_bytes, block;  transmission_t temp;  struct client_params *p = arg;    // Initialisation  PR_DBG( 2,"Connected client %d\n", p->id );  while ( 1 ) {    // Receive    pthread_mutex_lock( &mutex_rcv );    block = tx_block;    nbr_bytes = recv( p->sockfd, &temp, sizeof( transmission_t ), MSG_WAITALL );    if ( nbr_bytes != sizeof( transmission_t ) ) {      // The connection failed or the client sent some bogus data      PR_DBG( 2, "client(%i) disconnecting\n", p->id );      break;    } else {      // Update the gains, get_data_type(real or cpmx) and copy the data      is_complex=temp.is_complex;       rx_gain[p->id] = pow( 10.0, temp.rx_gain / 10 );      tx_gain[p->id] = pow( 10.0, temp.tx_gain / 10 );      PR_DBG( 4,"client(%i): slot:%i, block_count: %i, rcvd:%i, "	      "rx_gain =%e, tx_gain =%e\n",	      p->id, slot, temp.block_count, nbr_bytes,	      temp.rx_gain, temp.tx_gain );      memcpy( tx_signal_buffer[p->id][BLOCK_ACT_TX(block)],	      temp.signal, DAQ_DMA_BLOCK_SIZE_BYTES );            if ( BLOCK_ACT_TX(block) == BLOCK_BUFFER ) {	// The end of the buffer, copy to the beginning	memcpy( tx_signal_buffer[p->id][0],		temp.signal, DAQ_DMA_BLOCK_SIZE_BYTES );      }            nbr_ready_to_send++;      pthread_cond_broadcast( &cond_rcv );    }        // Send    pthread_mutex_lock( &mutex_send );    pthread_mutex_unlock( &mutex_rcv );    pthread_cond_wait( &cond_send, &mutex_send );    nbr_bytes = send( p->sockfd, rx_signal_buffer[p->id][BLOCK_ACT_TX(block)],		      DAQ_DMA_BLOCK_SIZE_BYTES, 0 );    PR_DBG( 4,"client(%i): slot:%i, sent:%i\n", p->id, slot, nbr_bytes );    pthread_mutex_unlock( &mutex_send );  }    // Cleanup and tell master-thread  close( p->sockfd );  nbr_clients--;  p->id = -1;  pthread_cond_broadcast( &cond_rcv );  pthread_mutex_unlock( &mutex_rcv );  if ( !nbr_clients ) {    serving = 0;  }  return NULL;}/** * Master-thread, makes sure that everybody is in synch, and that no users * get added at undue time. */static void *t_master() {  pthread_mutex_lock( &mutex_rcv );  nbr_ready_to_send = 0;  while( 1 ) {    PR_DBG( 4, "\n" );    PR_DBG( 4, "master: Sending ready to receive : nbr_clients = %d\n", nbr_clients );    // Clients receive data    do {      pthread_cond_wait( &cond_rcv, &mutex_rcv );      PR_DBG( 4, "master: Received %i out of %i\n", nbr_ready_to_send, nbr_clients );    } while ( nbr_ready_to_send < nbr_clients );    nbr_ready_to_send = 0;    PR_DBG( 4, "Going to calculate channel\n" );    // Calculate the channel    switch( 2 ) {    case 0:      // Flat channel, only sum of signals      flat_calc( nbr_clients );      break;    case 1:      // Fading channel, no reflexions      fading_calc( nbr_clients );      break;    case 2:      // Fading, multi-path channel with noise      if(is_complex){	fading_multi_complex_calc( nbr_clients,gid );      }else{	fading_multi_calc( nbr_clients,gid );      }      break;    }    if ( !( slot % 1000 ) ) {      PR_DBG( 3, "master: Generated slot %d for %d clients\n", slot, nbr_clients );    }    pthread_mutex_lock( &mutex_send );    // Clients send data    PR_DBG( 4, "master: Broadcast RTX\n" );    pthread_cond_broadcast( &cond_send );    pthread_mutex_unlock( &mutex_send );    tx_block++;    slot++;  }}int new_client( int fd ) {  struct client_params *p;  int i;  int nbr_bytes;  connect_t conn;    // If we get mutex_rcv, t_master must be in it's cond_wait,  // and thus we can add clients without messing things up.  if( !got_rcv_mutex ){    pthread_mutex_lock( &mutex_rcv );    PR_DBG( 2, "Got mutex_rcv!!!\n");  }  got_rcv_mutex=1;  // Search for an empty entry  for ( i=0; ( client[i].id != -1 ) && ( i < MAX_CLIENTS ); i++ ){}  if ( i >= MAX_CLIENTS ) {    PR_DBG( 0, "Server-table is full. Disconnect clients or higher MAX_CLIENTS\n" );    pthread_mutex_unlock( &mutex_rcv );    return -1;  }  PR_DBG( 2, "Getting new client at %i%%BLOCK_BUFFER=%i, block is %i\n",          tx_block, tx_block % BLOCK_BUFFER, BLOCK_ACT_TX( tx_block ) );    p = &client[i];  p->sockfd = fd;  p->id = i;   nbr_clients++;  nbr_bytes = recv( p->sockfd, &conn, sizeof( connect_t ), MSG_WAITALL );  PR_DBG( 3, "Received client %d info (%d bytes of %d)\n",          p->id, nbr_bytes, sizeof( connect_t ) );    if ( conn.indicator != INDICATOR_ID ) {    PR_DBG( 0, "Wrong indicator. Killing client %d\n",p->id);    return -1;  } else {    if( conn.gid==-1 ){      conn.gid=gid;    }    p->gid=gid;    PR_DBG( 2, "client[%i] has gid[%i]\n",p->id,p->gid);    nbr_bytes = send( p->sockfd, &conn, sizeof( connect_t ), MSG_WAITALL );    pthread_create( &p->thr, NULL, t_client, p );       PR_DBG( 2, "nbr_clients=%i, total_channels=%i, cond=%d\n",	   nbr_clients, conn.total_channels, !((nbr_clients)%conn.total_channels));    if( !((nbr_clients)%conn.total_channels) ){      pthread_mutex_unlock( &mutex_rcv );      PR_DBG( 4, "Released mutex_rcv!!!\n");      got_rcv_mutex=0;      PR_DBG( 2, "gid=%i\n", gid );      gid++;    }  }  return p->id;}/** * Initialise all variables */int init_server() {  int listenfd, i;  struct sockaddr_in servaddr;  int port;  FILE *f_port;  char path[256];  fading_multi_complex_init();  fading_multi_init();  fading_init();  flat_init();  init_command();  nbr_ready_to_rcv = 0;  nbr_ready_to_send = 0;  nbr_clients = 0;  slot = 0;  ready_to_rcv = 0;  ready_to_xmit = 0;  tx_block = 0;  serving = 1;  got_rcv_mutex = 0;  pthread_mutex_init( &mutex_rcv, NULL );  pthread_mutex_init( &mutex_send, NULL );  pthread_cond_init( &cond_rcv, NULL );  pthread_cond_init( &cond_rcv, NULL );  if ( (listenfd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {    return -1;  }  // Search for a free port  for ( port = SERV_PORT; port < SERV_PORT + 0x100; port++ ) {    memset( &servaddr, 0, sizeof(servaddr) );    servaddr.sin_family = AF_INET;    servaddr.sin_addr.s_addr = htonl( INADDR_ANY );    servaddr.sin_port = htons( port );    if ( bind( listenfd, (struct sockaddr*) &servaddr, sizeof( servaddr ) ) >= 0 ) {      break;    }  }  if ( port < SERV_PORT + 0x100 ) {    PR_DBG( 1, "Found port %i to be free\n", port );    // And write it to the config-file    snprintf( path, 256, "/tmp/%s", getenv( "USER" ) );    mkdir( path, 0777 );    strcat( path, "/server_port" );    f_port = fopen( path, "w" );    if ( !f_port ) {      PR_DBG( 0, "Error while opening %s. Stopping\n", path );      return -1;    }    fprintf( f_port, "%i\n", port );    fclose( f_port );  } else {    PR_DBG( 0, "No ports free anymore. Try again later\n" );    return -1;  }  if ( listen( listenfd, SOMAXCONN ) < 0 ) {    return -1;  }  for ( i=0; i < MAX_CLIENTS; i++ ) {    client[i].id = -1;  }  return listenfd;}/** * Initialises the server and waits for new connections */int main(int argc, char **argv) {  int listenfd, fd, id;  pthread_t master_thread;  socklen_t clilen;  struct sockaddr_in cliaddr;  if ( ( listenfd = init_server() ) < 0 ) {    PR_DBG( 0, "Couldn't create socket. Another server running here?\n" );    return 0;  }  pthread_create( &master_thread, NULL, &t_master, NULL );  while ( 1 ) {    clilen = sizeof( cliaddr );    PR_DBG( 3, "Waiting for new client\n" );    fd = accept( listenfd, (struct sockaddr*)&cliaddr, &clilen );    if ( fd > 0 ) {      PR_DBG( 1,"new client connected. ID=%i with fd #%d, block is %i\n",              id, fd, BLOCK_ACT_TX( tx_block ) );      id = new_client( fd );    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -