Should I call evhttp_request_free to release resource in http server? - http

I use libevent2.1.1 to write a simple http server, I think I should release evhttp_request with evhttp_request_free in http_server_callback. but when I run it, error happened. Please tell me why, and what I should do.
void http_server_callback (struct evhttp_request *req, void *arg)
{
evhttp_send_reply (req, HTTP_OK, "OK", NULL);
evhttp_request_free(req);
}
int http_server_run (void)
{
struct event_base *base;
struct evhttp *http;
struct evhttp_bound_socket *handle;
base = event_base_new ();
if (! base)
{
fprintf (stderr, "Couldn't create an event_base: exiting\n");
return 1;
}
http = evhttp_new (base);
if (! http)
{
fprintf (stderr, "couldn't create evhttp. Exiting.\n");
return 1;
}
evhttp_set_gencb (http, http_server_callback, NULL);
handle = evhttp_bind_socket_with_handle (http, "127.0.0.1", 8888);
if (! handle)
{
fprintf (stderr, "couldn't bind to port 8888. Exiting.\n");
return 1;
}
event_base_dispatch (base);
return 0;
}
int main (void)
{
WSADATA WSAData;
WSAStartup (0x101, &WSAData);
http_server_run();
return 0;
}
thanks in advance

the req will be freed in the callback function evhttp_send_done when server finishes writing. So it results in a double free.
the source code in libevent:
static void
evhttp_send_done(struct evhttp_connection *evcon, void *arg)
{
int need_close;
struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
TAILQ_REMOVE(&evcon->requests, req, next);
need_close =
(REQ_VERSION_BEFORE(req, 1, 1) &&
!evhttp_is_connection_keepalive(req->input_headers))||
evhttp_is_connection_close(req->flags, req->input_headers) ||
evhttp_is_connection_close(req->flags, req->output_headers);
EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
evhttp_request_free(req);
...
}

Related

C - simple http server + directory listening

Here is a working example of a simple HTTP server written in C (working well for it's purpose)
But what I try to achieve/understand is how to implement directory listening!!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<signal.h>
#include<fcntl.h>
#include <dirent.h>
#define CONNMAX 100
#define BYTES 1024
char* directory;
struct dirent *dirst;
DIR *dir;
char *ROOT;
int listenfd, clients[CONNMAX];
void error(char *);
void startServer(char *);
void respond(int);
int main(int argc, char* argv[])
{
struct sockaddr_in clientaddr;
socklen_t addrlen;
char c;
//Default Values PATH = ~/ and PORT=10000
char PORT[6];
ROOT = getenv("PWD");
strcpy(PORT,"10000");
int slot=0;
//Parsing the command line arguments
while ((c = getopt (argc, argv, "p:r:")) != -1)
switch (c)
{
case 'r':
ROOT = malloc(strlen(optarg));
strcpy(ROOT,optarg);
break;
case 'p':
strcpy(PORT,optarg);
break;
case '?':
fprintf(stderr,"Wrong arguments given!!!\n");
exit(1);
default:
exit(1);
}
printf("Server started at port no. %s%s%s with root directory as %s%s%s\n","\033[92m",PORT,"\033[0m","\033[92m",ROOT,"\033[0m");
// Setting all elements to -1: signifies there is no client connected
int i;
for (i=0; i<CONNMAX; i++)
clients[i]=-1;
startServer(PORT);
// ACCEPT connections
while (1)
{
addrlen = sizeof(clientaddr);
clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);
if (clients[slot]<0)
error ("accept() error");
else
{
if ( fork()==0 )
{
respond(slot);
exit(0);
}
}
while (clients[slot]!=-1) slot = (slot+1)%CONNMAX;
}
return 0;
}
//start server
void startServer(char *port)
{
struct addrinfo hints, *res, *p;
// getaddrinfo for host
memset (&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo( NULL, port, &hints, &res) != 0)
{
perror ("getaddrinfo() error");
exit(1);
}
// socket and bind
for (p = res; p!=NULL; p=p->ai_next)
{
listenfd = socket (p->ai_family, p->ai_socktype, 0);
if (listenfd == -1) continue;
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break;
}
if (p==NULL)
{
perror ("socket() or bind()");
exit(1);
}
freeaddrinfo(res);
// listen for incoming connections
if ( listen (listenfd, 1000000) != 0 )
{
perror("listen() error");
exit(1);
}
}
//client connection
void respond(int n)
{
char mesg[99999], *reqline[3], data_to_send[BYTES], path[99999];
int rcvd, fd, bytes_read;
memset( (void*)mesg, (int)'\0', 99999 );
rcvd=recv(clients[n], mesg, 99999, 0);
if (rcvd<0) // receive error
fprintf(stderr,("recv() error\n"));
else if (rcvd==0) // receive socket closed
fprintf(stderr,"Client disconnected unexpectedly.\n");
else // message received
{
// printf("%s", mesg);
reqline[0] = strtok (mesg, " \t\n");
if ( strncmp(reqline[0], "GET\0", 4)==0 )
{
reqline[1] = strtok (NULL, " \t");
reqline[2] = strtok (NULL, " \t\n");
if ( strncmp( reqline[2], "HTTP/1.0", 8)!=0 && strncmp( reqline[2], "HTTP/1.1", 8)!=0 )
{
write(clients[n], "HTTP/1.0 400 Bad Request\n", 25);
}
else
{
if ( strncmp(reqline[1], "/\0", 2)==0 )
reqline[1] = "/index.html"; //Because if no file is specified, index.html will be opened by default (like it happens in APACHE...
strcpy(path, ROOT);
strcpy(&path[strlen(ROOT)], reqline[1]);
printf("Serving: %s\n", path);
if ( (fd=open(path, O_RDONLY))!=-1 ) //FILE FOUND
{
send(clients[n], "HTTP/1.0 200 OK\n\n", 17, 0);
while ( (bytes_read=read(fd, data_to_send, BYTES))>0 )
write (clients[n], data_to_send, bytes_read);
}
else write(clients[n], "HTTP/1.0 404 Not Found\n", 23); //FILE NOT FOUND
}
}
}
//Closing SOCKET
shutdown (clients[n], SHUT_RDWR); //All further send and recieve operations are DISABLED...
close(clients[n]);
clients[n]=-1;
}
gcc -Wall -Wextra -Werror simplehttp.c -o http
./http -p 9090 -r /home/configs
Now, in browser if i type address http://localhost:9090 => got error( because index,html is missing)
As I'm still rusty in C(trying to get back in shape), i try to modify the code to allow also dir listen :)
Any help is much appreciate :)

Receive and Send in Tinyos

I have a program comunication communication between two telosb. It is a example of tinyos: https://github.com/tinyos/tinyos-release/tree/tinyos-2_1_2/apps/RadioCountToLeds. This code will send and receive a value count, if the conditions meet, it will turn on the corresponding led. I want to split the code into 2 parts: Send and Receive. And i create 2 app:
Receive:
//RadioCountToLedC.nc
#include "Timer.h"
#include "RadioCountToLeds.h"
module RadioCountToLedsC #safe() {
uses {
interface Leds;
interface Boot;
interface Receive;
interface Packet;
}
}
implementation {
message_t packet;
uint16_t counter = 0;
event void Boot.booted()
{
}
event message_t* Receive.receive(message_t* bufPtr,
void* payload, uint8_t len) {
call Leds.led0On();
dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len);
if (len != sizeof(radio_count_msg_t)) {return bufPtr;}
else {
radio_count_msg_t* rcm = (radio_count_msg_t*)payload;
if (rcm->counter%3 == 0) {
call Leds.led0On();
}
else {
call Leds.led0Off();
}
if (rcm->counter%3 == 1) {
call Leds.led1On();
}
else {
call Leds.led1Off();
}
if (rcm->counter%3 == 2) {
call Leds.led2On();
}
else {
call Leds.led2Off();
}
return bufPtr;
}
}
}
//RadioToLedAppC.nc
#include "RadioCountToLeds.h"
configuration RadioCountToLedsAppC {}
implementation {
components MainC, RadioCountToLedsC as App, LedsC;
components new AMReceiverC(AM_RADIO_COUNT_MSG);
components new TimerMilliC();
components ActiveMessageC;
}
Send:
//RadioCountToLedC.nc
#include "Timer.h"
#include "RadioCountToLeds.h"
module RadioCountToLedsC #safe() {
uses {
interface Leds;
interface Boot;
interface AMSend;
interface Timer<TMilli> as MilliTimer;
interface SplitControl as AMControl;
interface Packet;
}
}
implementation {
message_t packet;
bool locked;
uint16_t counter = 0;
event void Boot.booted() {
call MilliTimer.startPeriodic(250);
call AMControl.start();
}
event void AMControl.startDone(error_t err) {
if (err == SUCCESS) {
call MilliTimer.startPeriodic(250);
}
else {
call AMControl.start();
}
}
event void AMControl.stopDone(error_t err) {
// do nothing
}
event void MilliTimer.fired() {
if(counter<100){
counter++;
}else{
counter=0;
}
dbg("RadioCountToLedsC", "RadioCountToLedsC: timer fired, counter is %hu.\n", counter);
if (locked) {
return;
}
else {
radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t));
if (rcm == NULL) {
return;
}
rcm->counter = counter;
if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) == SUCCESS) {
dbg("RadioCountToLedsC", "RadioCountToLedsC: packet sent.\n", counter);
locked = TRUE;
}
}
}
event void AMSend.sendDone(message_t* bufPtr, error_t error) {
if (&packet == bufPtr) {
locked = FALSE;
}
}
}
//RadioToLedAppC.nc
#include "RadioCountToLeds.h"
configuration RadioCountToLedsAppC {}
implementation {
components MainC, RadioCountToLedsC as App, LedsC;
components new AMSenderC(AM_RADIO_COUNT_MSG);
components new AMReceiverC(AM_RADIO_COUNT_MSG);
components new TimerMilliC();
components ActiveMessageC;
App.Boot -> MainC.Boot;
App.AMSend -> AMSenderC;
App.AMControl -> ActiveMessageC;
App.Leds -> LedsC;
App.MilliTimer -> TimerMilliC;
App.Packet -> AMSenderC;
}
RadioCountToLed.h
#ifndef RADIO_COUNT_TO_LEDS_H
#define RADIO_COUNT_TO_LEDS_H
typedef nx_struct radio_count_msg {
nx_uint16_t counter;
} radio_count_msg_t;
enum {
AM_RADIO_COUNT_MSG = 6,
};
#endif
But when i run it don't work. If i write Receive and Send in same file RadioCountToLedC.nc as above example. It will work well. What's wrong with my application?
I think you need to
call AMControl.start();
In your booted function of your Receiver. This will turn the radio on and allow you to receive messages.
PS If this doesn't completely solve your problem please provide more detail on what you observe happening when you run.
The are a number of easy ways to tackle this, the easiest way is to just have a variable that controls program flow or alternatively use each nodes TinyOS ID to control flow.
For example you could have (Only 4 small changes have been made):
#include "Timer.h"
#include "RadioCountToLeds.h"
/**
* Implementation of the RadioCountToLeds application. RadioCountToLeds
* maintains a 4Hz counter, broadcasting its value in an AM packet
* every time it gets updated. A RadioCountToLeds node that hears a counter
* displays the bottom three bits on its LEDs. This application is a useful
* test to show that basic AM communication and timers work.
*
* #author Philip Levis
* #date June 6 2005
*/
module RadioCountToLedsC #safe() {
uses {
interface Leds;
interface Boot;
interface Receive;
interface AMSend;
interface Timer<TMilli> as MilliTimer;
interface SplitControl as AMControl;
interface Packet;
}
}
implementation {
message_t packet;
bool locked;
uint16_t counter = 0;
enum state {TX, RX} mode; //Change 1: Define States
event void Boot.booted() {
call AMControl.start();
mode = RX; // CHANGE 2: Set States - "RX" for receiver & "TX" for transmitter
}
event void AMControl.startDone(error_t err) {
if (err == SUCCESS) {
if(mode == TX) //CHANGE 3: Only the transmitter sends
call MilliTimer.startPeriodic(250);
}
else {
call AMControl.start();
}
}
event void AMControl.stopDone(error_t err) {
// do nothing
}
event void MilliTimer.fired() {
counter++;
dbg("RadioCountToLedsC", "RadioCountToLedsC: timer fired, counter is %hu.\n", counter);
if (locked) {
return;
}
else {
radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t));
if (rcm == NULL) {
return;
}
rcm->counter = counter;
if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) == SUCCESS) {
dbg("RadioCountToLedsC", "RadioCountToLedsC: packet sent.\n", counter);
locked = TRUE;
}
}
}
event message_t* Receive.receive(message_t* bufPtr,
void* payload, uint8_t len) {
dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len);
if(mode == TX) return bufPtr; //CHANGE 4: Only RX processes packets
if (len != sizeof(radio_count_msg_t)) {return bufPtr;}
else {
radio_count_msg_t* rcm = (radio_count_msg_t*)payload;
if (rcm->counter & 0x1) {
call Leds.led0On();
}
else {
call Leds.led0Off();
}
if (rcm->counter & 0x2) {
call Leds.led1On();
}
else {
call Leds.led1Off();
}
if (rcm->counter & 0x4) {
call Leds.led2On();
}
else {
call Leds.led2Off();
}
return bufPtr;
}
}
event void AMSend.sendDone(message_t* bufPtr, error_t error) {
if (&packet == bufPtr) {
locked = FALSE;
}
}
}
Instead of setting the mode in the Booted event, you can alternatively use the C preprocessor to set the mode variable if you wish.
The problem with the receiver application that you made is that it
i) Does not start the transceiver as it does not call AMControl.start() in the Boot.Booted() event.
ii) The wiring in the RadioCountToLedsAppC is not correct as no interfaces are connected. You need to connect all interfaces (Boot, Leds, Receive and AMControl). Similar to how you had connected them in the sender.

ev in redisAsyncContext

In redisAsyncContext, stuct ev was defined:
struct {
void *data;
void (*addRead)(void *privdata);
void (*delRead)(void *privdata);
void (*addWrite)(void *privdata);
void (*delWrite)(void *privdata);
void (*cleanup)(void *privdata);
} ev;
There is a function:
void CleanUpEvent()
{
if (m_pstContext->ev.delRead)
{
m_pstContext->ev.delRead(m_pstContext->ev.data);
}
if (m_pstContext->ev.delWrite)
{
m_pstContext->ev.delWrite(m_pstContext->ev.data);
}
}
How it works? When should I use ev?
Basically you need to provide only connect and disconnect callbacks, rest of things hiredis will do for you alone.
#include <hiredis.h>
#include <async.h>
#include <adapters/libuv.h>
void connectCallback(const redisAsyncContext *c, int status);
void disconnectCallback(const redisAsyncContext *c, int status);
void getCallback(redisAsyncContext *c, void *r, void *privdata);
int main (int argc, char **argv) {
//make a async context
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
if (c->err) {
/* Let *c leak for now... */
printf("Error: %s\n", c->errstr);
return 1;
}
//now, you need to attach hiredis to your event loop, its depends on event lib that you are using
//example for libuv
redisLibuvAttach(c, uv_default_loop());
//now we setup callbacks
redisAsyncSetConnectCallback(c, connectCallback);
redisAsyncSetDisconnectCallback(c, disconnectCallback);
//enquee "SET foo bar" without callback
redisAsyncCommand(c, NULL, NULL, "SET foo %b", "bar", strlen("bar"));
//enquee "GET foo" with callback and privdata "end-1"
redisAsyncCommand(c, getCallback, (char*)"end-1", "GET foo");
//run your event loop
uv_run(loop, UV_RUN_DEFAULT);
return 0;
}
void connectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Connected...\n");
}
void disconnectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Disconnected...\n");
}
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
redisReply *reply = r;
if (reply == NULL) return;
printf("argv[%s]: %s\n", (char*)privdata, reply->str);
/* Disconnect after receiving the reply to GET */
redisAsyncDisconnect(c);
}
Check https://github.com/redis/hiredis/tree/master/examples for more examples on different event libraries.

Qt , QMutex: destroying locked mutex then app crash

I make an http operation(get,post etc...) by using QNetworkAccessManager. I run a few "get" operation in paralel. For this , I use QtConcurrent::run(this,&RestWebservice::GetHTTPData) to make multi HTTP operations.
My problem is When I close the app before HTTP operation does not complete , App is crashed.Application Output write this line QMutex: destroying locked mutex then write The program has unexpectedly finished.
I guest problem occurs in this line
void RestWebservice::get()
{
// mutex.lock();
m_networkManager.get(m_networkrequest);
// mutex.unlock();
}
But I am not sure because QtCreater Debugger is not good like VS.By the way , GetHTTPData is in different class.
MY CODE for start network Operation:(MobileOperation.cpp).For exapmle getUserAccount metod start a http operation.
void MobileOperations::getWorkOrderListT(int ekipId) {
MyGlobal::Metods metod=MyGlobal::EkipIsEmriListesi;
QString parameters="{EkipId}";
QMap<QString,QVariant> paramlist;
paramlist["EkipId"]=ekipId;
GetHTTPData(metod,parameters,paramlist);
if(m_workorder.IsSuccess==true)
{
// emit successupdatewo();
if(m_workorder.workorders.count()>0)
{
InsertWo(json.workorder->workorders);
emit processstop("İş Emri Listesi Güncellendi");
// QThread::sleep(2);
}
else
{
emit processstop(json.workorder->ReturnMessage);
}
emit successworkstart();
}
else
{
emit processstop("Bağlantı Başarısız Oldu");
}
}
void MobileOperations::getUserAccount(QString kullaniciAdi, QString sifre,bool isremember)
{
json.user=m_user;
QtConcurrent::run(this,&MobileOperations::getUserAccountT,kullaniciAdi,sifre,isremember);
// getUserAccountT(kullaniciAdi,sifre,isremember);
processstart("Baglaniyor");
}
void MobileOperations::GetHTTPData(MyGlobal::Metods MetodName, QString Parameters, QMap<QString, QVariant> paramlist)
{
try
{
parameter=new HttpRequest();
parameter->url=m_url;
parameter->metodname=MetodName;
parameter->resource=m_path;
parameter->appid=m_appid;
parameter->apppass=m_apppass;
parameter->parametersname=Parameters;
parameter->params=paramlist;
rest= new RestWebservice(parameter->GenerateHTTPQuery(),MetodName);
// json=new JSonParser();
// loop=new QEventLoop();
loop=new QEventLoop();
QObject::connect(rest,SIGNAL(sendhttpdata(QByteArray,MyGlobal::Metods)),&json,SLOT(onGetData(QByteArray,MyGlobal::Metods)));
QObject::connect(&json,SIGNAL(serilazitionCompleted()),loop,SLOT(quit()));
rest->get();
loop->exec();
}
catch(std::string &exp)
{
qDebug()<<"Sonlandırıldı";
}
}
MY CODE of classes For HTTP operatins :
#include "restwebservice.h"
#include <QJsonDocument>
#include<QJsonArray>
#include <QJsonObject>
#include<QJsonValue>
#include<QList>
#include <QThread>
RestWebservice::RestWebservice(QNetworkRequest request,
MyGlobal::Metods metod,
QObject* parent):QObject(parent),m_networkrequest(request),m_metodname(metod)
{
connect(&m_networkManager, SIGNAL(finished(QNetworkReply*)),this, SLOT(onResult(QNetworkReply*)));
// connect(&m_networkManager,SIGNAL())
}
void RestWebservice::get()
{
// mutex.lock();
m_networkManager.get(m_networkrequest);
// mutex.unlock();
}
void RestWebservice::post(QString request)
{
QByteArray requestA= request.toUtf8();
m_networkManager.post(m_networkrequest,requestA);
}
void RestWebservice::onResult(QNetworkReply* reply)
{
try
{
if (reply->error() != QNetworkReply::NoError)
{
qDebug()<<reply->error()<<":"<<reply->errorString();
MyGlobal::NetworkStatus=reply->errorString();
emit sendhttpdata(m_data,m_metodname);
return;
// throw(reply->errorString().toStdString());
}
QByteArray data = reply->readAll();
reply->deleteLater();
m_data=data;
MyGlobal::NetworkStatus="Tablolar Yüklendi";
emit sendhttpdata(m_data,m_metodname);
}
catch(std::string exp)
{
qDebug()<<"Exception:"<<QString::fromStdString(exp);
}
catch(std::exception &exp)
{
qDebug()<<"Exception:"<<QString::fromStdString(exp.what());
}
}
void RestWebservice::onError()
{
qDebug()<<"Hata VAR";
}
HttpRequest::HttpRequest(QObject *parent) :
QObject(parent)
{
}
QNetworkRequest HttpRequest::GenerateHTTPQuery()
{
// QString path="";
QString path=QString("/%1/%2/%3/%4/%5").arg(resource).arg(MyGlobal::getMetodName(metodname)).arg(appid).arg(apppass).arg(parametersname);
foreach (QString param, params.keys()) {
path.replace("{"+param+"}",params[param].toString());
}
QUrl m_url(url);
m_url.setPath(path);
m_request.setUrl(m_url);
m_request.setRawHeader("Content-Type","application/json;charset=utf-8");
// m_request.setRawHeader("SOAPAction","http://tempuri.org/IMobileClient/UserAuth");
qDebug()<<m_url.url();
return m_request;
}
QNetworkRequest HttpRequest::GenerateHTTPQueryPost()
{
// QString path="";
QString path=QString("/%1/%2").arg(resource).arg(MyGlobal::getMetodName(metodname));
QUrl m_url(url);
m_url.setPath(path);
m_request.setUrl(m_url);
m_request.setRawHeader("Content-Type","application/json;charset=utf-8");
// m_request.setRawHeader("SOAPAction","http://tempuri.org/IMobileClient/UserAuth");
qDebug()<<m_url.url();
return m_request;
}
Is you mutex a member of your class. In that case the mutex is destructed before it is unlocked (as I presume the containing class goes out of scope), which causes the message you see. The destructor of the mutex is called when the class is destructed, while the lock is held. This is a problem. Typically you will have to find a way to not block indefinitely during your network request.

Multithreaded client server problem

I am facing a peculiar problem with my clients server application.
I have written a console based multithreaded client server.
Multiple Client try to send and receive data thousand times.
When i run more than one client, my old client stops sending receiving data and new client starts operation.
I am unable to understand why my first client gets blocked when i start another client.
Here I have added some code.
These are TCP operations.I have just mentioned key functions.
bool LicTCPServer::Initialize()
{
m_socketAccept = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (m_socketAccept == INVALID_SOCKET)
return false;
int *p_int;
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(m_socketAccept, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(m_socketAccept, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", WSAGetLastError());
free(p_int);
}
free(p_int);
/*int iMode = 1;
ioctlsocket(m_socketAccept, FIONBIO, (u_long FAR*) &iMode);*/
SOCKADDR_IN oSockAddr;
::ZeroMemory(&oSockAddr, sizeof(SOCKADDR_IN));
oSockAddr.sin_family = AF_INET;
oSockAddr.sin_port = htons(m_wPortNoServer);
oSockAddr.sin_addr.s_addr = m_dwInetAddrServer;
int ret = bind(m_socketAccept, (const sockaddr*) &oSockAddr, sizeof(SOCKADDR_IN));
int error;
if (ret == SOCKET_ERROR)
{
closesocket(m_socketAccept);
error = WSAGetLastError();
return false;
}
error = listen(m_socketAccept, SOMAXCONN);
DWORD temp = GetLastError();
if (error == SOCKET_ERROR)
return false;
return true;
}
bool LicTCPServer::CheckConnection(struct sockaddr_in *clientAddress, SOCKET *sockValue)
{
//struct sockaddr_in clientAddress1;
int clientAddressLen = sizeof(struct sockaddr_in);
//struct sockaddr_in clientAddress; // Address of the client that sent data
SOCKET socket = accept(m_socketAccept, (struct sockaddr *)clientAddress, &clientAddressLen);
printf("Port - %d \n",clientAddress->sin_port);
//m_socketConnect = socket;
*sockValue = socket;
return true;
}
int LicTCPServer::ReceiveData(SOCKET socketNo, char* pszBuf, int & bufLen)
{
/*struct timeval tvTimeout;
tvTimeout.tv_sec = 0;
tvTimeout.tv_usec = (long) (10 * 1000);
fd_set fdSet;
FD_ZERO(&fdSet);
FD_SET(socketNo, &fdSet);
long lStatus = select(socketNo + 1, &fdSet, NULL, NULL, &tvTimeout);
if (lStatus <= 0)
{
FD_ZERO(&fdSet);
}
if (!FD_ISSET(socketNo, &fdSet))
{
return 0;
}*/
/*if (!CanReadOnBlockingSocket(socketNo))
{
return TELEGRAM_RECEIVE_ERROR;
}*/
bufLen = recv(socketNo, pszBuf, 10, 0);
if(bufLen == -1)
return WSAGetLastError();
else if(bufLen == 0)
{
closesocket(socketNo);
return -1;
}
else
return 0;
}
bool LicTCPServer::SendData(SOCKET socketNo, BYTE *puchBuf, int iBufLen)
{
int ret = send(socketNo, (char*)puchBuf, iBufLen,0);
//printf("Sent from server: %d %d\n\n",test2.a,test2.b);
return true;
}
Here is my main() function:
void ClientServerCommunication(void *dummy);
struct informationToClient
{
LicTCPServer *serverFunctions;
SOCKET clientSocketNo;
}infoToClient;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwInetAddrServer = inet_addr("127.0.0.1");
if(dwInetAddrServer == INADDR_NONE)
return 0;
WORD dwPortNumber = 2001;
LicTCPServer server(dwInetAddrServer, dwPortNumber);
server.Initialize();
struct sockaddr_in clientAddress;
SOCKET sockValue;
infoToClient.serverFunctions = &server;
while(1)
{
bool retValue = server.CheckConnection(&clientAddress, &sockValue);
if( sockValue == INVALID_SOCKET )
{
Sleep(10000);
continue;//or exit from thread
}
infoToClient.clientSocketNo = sockValue;
//retrieve client information from Make Connection and put it into LicenseClientData class
//Create thread for each client which will receive or send data
_beginthread(ClientServerCommunication, 0, (void *)&infoToClient);
//delete
}
return 0;
}
void ClientServerCommunication(void *dummy)
{
int iRetValue;
informationToClient *socketInfo = (informationToClient *)dummy;
char szBuf[10];
int iBufLen = 0;
while(1)
{
iRetValue = socketInfo->serverFunctions->ReceiveData(socketInfo->clientSocketNo, szBuf, iBufLen);
printf("Data received on socket %d %s\n", socketInfo->clientSocketNo, szBuf);
if(iRetValue == WSAECONNRESET)
{
_endthread();
}
socketInfo->serverFunctions->SendData(socketInfo->clientSocketNo, (BYTE*)szBuf, iBufLen);
printf("Data sent on socket %d %s\n", socketInfo->clientSocketNo, szBuf);
}
}
All the code mentioned above is a testing code.Once it works fine then I have to use LicTCPServer class in my application.
There are many possible errors.
Your description is consistent with you storing the 'connection' as a global variable, rather than giving each thread on the server its own connection instance.
Update:
quick glance at the code, infoToClient is global.

Resources