Sunday 17 July 2016

Pulse Code Modulation and Netowrking using QT and C++

Q: Write a program for Pulse Code Modulation and send the data to a server

Introduction

This is C++ code for both the client and the server to implement PCM and netowrking. The Client is a GUI program while server is terminal based.

 

Software Requirements

Os: Ubuntu 14.04 LTS
FrameWork: QT
Language: C++

Prequisites
Client-Server Programing
Understanding of QT framework
Basic Graphics Concepts
QImage Class

Project Structure


Divided into two parts Server and Client

Server

Server Code is slight modified version of code from http://www.bogotobogo.com/cplusplus/sockets_server_client.php.
This site has nice explanation for the server code.
/* The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     // create a socket
     // socket(int domain, int type, int protocol)
     sockfd =  socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");

     // clear address structure
     bzero((char *) &serv_addr, sizeof(serv_addr));

     portno = atoi(argv[1]);

     /* setup the host_addr structure for use in bind call */
     // server byte order
     serv_addr.sin_family = AF_INET;  

     // automatically be filled with current host's IP address
     serv_addr.sin_addr.s_addr = INADDR_ANY;  

     // convert short integer value for port must be converted into network byte order
     serv_addr.sin_port = htons(portno);

     // bind(int fd, struct sockaddr *local_addr, socklen_t addr_length)
     // bind() passes file descriptor, the address structure, 
     // and the length of the address structure
     // This bind() call will bind  the socket to the current IP address on port, portno
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");

     // This listen() call tells the socket to listen to the incoming connections.
     // The listen() function places all incoming connection into a backlog queue
     // until accept() call accepts the connection.
     // Here, we set the maximum size for the backlog queue to 5.
     listen(sockfd,5);

     // The accept() call actually accepts an incoming connection
     clilen = sizeof(cli_addr);

     // This accept() function will write the connecting client's address info 
     // into the the address structure and the size of that structure is clilen.
     // The accept() returns a new socket file descriptor for the accepted connection.
     // So, the original socket file descriptor can continue to be used 
     // for accepting new connections while the new socker file descriptor is used for
     // communicating with the connected client.
     
     newsockfd = accept(sockfd, 
                 (struct sockaddr *) &cli_addr, &clilen);
     if (newsockfd < 0) 
          error("ERROR on accept");
 

     // This send() function sends the 14 bytes of the string to the new socket
     send(newsockfd, "Data Recieved", 14, 0);
     bzero(buffer,256);

     n = read(newsockfd,buffer,255);
     if (n < 0) error("ERROR reading from socket");
     printf("Here is the data: %s\n",buffer);
     close(newsockfd);
     close(sockfd);
     return 0; 
}

Client Code 

Uses some code from http://www.bogotobogo.com/cplusplus/sockets_server_client.php.


MainWindow.h

//Code by Abhishek Munagekar for prgwonders.blogspot.in
#ifndef MAINWINDOW_H 
#define MAINWINDOW_H

#include <QMainWindow>
#include <QImage>

# define BMARGIN 30;
# define TMARGIN 30;
# define LMARGIN 30;
# define RMARGIN 30;
# define IWIDTH 660;
# define IHEIGHT 660;


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    void drawaxes();
    void drawsine();
    void setamplitudes(int,int,int,int);
    int sign(float);
    void dda(int,int,int,int);
    void qgen(int,int);
    void send(char[],std::string,std::string);
    void error(const char* msg);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    QImage img;
    QRgb gcolor;
    float yval[600];
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "math.h"
#include "iostream"
#include <sstream>
#include "string"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

using namespace std;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    img=QImage(661,661,QImage::Format_RGB888);
    this->gcolor=qRgb(0,255,0);
    ui->label_3->setPixmap(QPixmap::fromImage(img));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    int scalex=ui->lineEdit_3->text().toInt();
    int scaley=ui->lineEdit_4->text().toInt();
    int amp=ui->lineEdit->text().toInt();
    int tp=ui->lineEdit_2->text().toInt();
    int qbits=ui->lineEdit_5->text().toInt();
    int npts=ui->lineEdit_6->text().toInt();
    this->drawaxes();
    this->setamplitudes(amp,tp,scalex,scaley);
    this->drawsine();
    this->qgen(npts,qbits);
    ui->label_3->setPixmap(QPixmap::fromImage(img));
}

void MainWindow::drawaxes(){
    int ycord=IHEIGHT;
    ycord/=2;
    //drawing of x axis
    int i;
    for(i=30;i<=630;i++){
        img.setPixel(i,ycord,gcolor);
    }
    //drawing of y axis
    int xcord=LMARGIN;

    for(i=30;i<=630;i++){
        img.setPixel(xcord,i,gcolor);
    }

}

void MainWindow ::setamplitudes(int amp,int tp, int scalex,int scaley){
    int i;
    for(i=0;i<=600;i++){//complex formulat for plotting
        yval[i]=float(amp)/scaley*300*sin(2*3.142*scalex/tp*i/600);

    }
}

void MainWindow ::drawsine(){
    int x;

    for(x=0;x<=600;x++){
        img.setPixel(x+30,int(329.5-yval[x]),gcolor);//Rounding off included

    }
    //Improvement of graphics goes below
    for(x=1;x<=600;x++){
        dda(x+29,329.5-yval[x-1],x+30,329.5-yval[x]);
    }

}

void MainWindow::dda(int x1,int y1,int x2,int y2){//Used for improving sine wave graphics
    int length=std::max(abs(x2-x1),abs(y2-y1));
    float dx=(x2-x1)/(float)length;
    float dy=(y2-y1)/(float)length;
    float x=x1+0.5*sign(dx);
    float y=y1+0.5*sign(dy);
    for(int i=1;i<=length;i++){
    img.setPixel(int(x),int(y),gcolor);
    x=dx+x;
    y=y+dy;
    }
}

void MainWindow :: qgen(int npts,int qbits){//quantization code generator
    std::cout<<"Bits to Send are:"<<endl;
    int i;
    char buffer[256],temp[256];
    float unit=2/(pow(2,qbits-1));
    for(i=0;i<npts;i++){//for npts samples
        yval[i] = sin(2 * 3.142 * i/(npts-1));//sampling done
        yval[i]+=1;//shift amplitude up
        yval[i]=(int)(yval[i]/unit+0.5);//divide and round off step
    }
    bzero(buffer,256);//zero out the buffer
    bzero(temp,256);
    for(int i=0;i<ui->lineEdit_6->text().toInt();i++){
        sprintf(temp,"%d\n",(int)yval[i]);
        strcat(buffer,temp);
        bzero(temp,256);
    }
    cout<<buffer<<endl;

    cout<<"Printing Client Side Data above"<<endl;
}

int MainWindow::sign(float num){//return modulus of the number
    return ((num<0)?-1:(num>0));
}

void MainWindow::on_pushButton_2_clicked() 
//this client side code is a slight modified n commented code from
//http://www.bogotobogo.com/cplusplus/sockets_server_client.php
{

    int portno=ui->lineEdit_8->text().toInt();
    char* host=ui->lineEdit_7->text().toLocal8Bit().data();
    int sockfd,n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    char buffer[256],temp[256];
    sockfd = socket(AF_INET, SOCK_STREAM, 0);//open the socket, and get socket descriptor
    if (sockfd < 0)
        error("ERROR opening socket");//if error
     server = gethostbyname(host);
     if (server == NULL) {//incase of invalid server
            fprintf(stderr,"ERROR, no such host\n");
            exit(0);
        }
      bzero((char *) &serv_addr, sizeof(serv_addr));//zero out the structure
      serv_addr.sin_family = AF_INET;//setting structure variables
      bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr,server->h_length);//copy from sever to serv_addr the host address
      serv_addr.sin_port = htons(portno);//host to network
      if (::connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)//blocking call
              error("ERROR connecting");
      cout<<"Connection to Server Successful\n";
      bzero(buffer,256);//zero out the buffer
      bzero(temp,256);
      for(int i=0;i<ui->lineEdit_6->text().toInt();i++){
          sprintf(temp,"%d\n",(int)yval[i]);
          strcat(buffer,temp);
          bzero(temp,256);
      }
      n = write(sockfd, buffer, strlen(buffer));
          if (n < 0)
               error("ERROR writing to socket");
          bzero(buffer,256);
          n = read(sockfd, buffer, 255);
          if (n < 0)
               error("ERROR reading from socket");
          cout<<buffer<<endl;
          ::close(sockfd);
}

void MainWindow::error(const char *msg){
    perror(msg);
        exit(0);
}


Outputs


Client
Bits to Send are:
8
13
16
15
11
51
0
3
8

Printing Client Side Data above
Connection to Server Successful
Data Recieved

Server

student@comp:~$ ./server 7777
Here is the data: 8
13
16
15
11
5
1
0
3
8

Screenshot



Pulse Code Modulation


Project Resources

All Codes and Screenshots here: mediafire
In case of any issues, feel free to solve them.



No comments:

Post a Comment