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.
Related
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 :)
I need to decode rtsp stream from Ip camera using ffmpeg, below is the code for decoder
ffmpeg_decoder.h
class ffmpeg_decoder
{
public:
ffmpeg_decoder();
int initial(QString & url);
int h264Decodec();
void close_stream();
virtual ~ffmpeg_decoder();
AVPicture picture;
int width;
int height;
QMutex mutex;
QImage imageDecoded;
private:
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVFrame *pFrame;
AVPacket packet;
SwsContext * pSwsCtx;
int videoStream;
QString rtspURL;
};
ffmpeg_decoder.cpp
ffmpeg_decoder::ffmpeg_decoder()
{
pCodecCtx = NULL;
videoStream=-1;
}
ffmpeg_decoder::~ffmpeg_decoder()
{
sws_freeContext(pSwsCtx);
}
int ffmpeg_decoder::initial(QString & url)
{
int err;
rtspURL=url;
AVCodec *pCodec;
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
pFrame = av_frame_alloc();
err = avformat_open_input(&pFormatCtx, rtspURL.toStdString().c_str(), NULL,
NULL);
if (err < 0)
{
printf("Can not open this file");
return -1;
}
if (avformat_find_stream_info(pFormatCtx,NULL) < 0)
{
printf("Unable to get stream info");
return -1;
}
int i = 0;
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
printf("Unable to find video stream");
return -1;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
width=pCodecCtx->width;
height=pCodecCtx->height;
avpicture_alloc(&picture,PIX_FMT_RGB24,pCodecCtx->width,pCodecCtx->height);
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
pSwsCtx = sws_getContext(width, height, PIX_FMT_YUV420P, width,
height, PIX_FMT_RGB24,
SWS_BICUBIC, 0, 0, 0);
if (pCodec == NULL)
{
printf("Unsupported codec");
return -1;
}
printf("video size : width=%d height=%d \n", pCodecCtx->width,
pCodecCtx->height);
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Unable to open codec");
return -1;
}
printf("initial successfully");
return 0;
}
int ffmpeg_decoder::h264Decodec()
{
int frameFinished=0;
// while (av_read_frame(pFormatCtx, &packet) >= 0)
if(av_read_frame(pFormatCtx, &packet) >= 0)
{
if(packet.stream_index==videoStream)
{
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (frameFinished)
{
printf("***************ffmpeg decodec*******************\n");
mutex.lock();
int rs = sws_scale(pSwsCtx, (const uint8_t* const *) pFrame->data,
pFrame->linesize, 0,
height, picture.data, picture.linesize);
imageDecoded = QImage();
imageDecoded= QImage(this->picture.data[0],this->width,this->height,QImage::Format_RGB888);
//imageDecoded = imageDecoded.copy();
mutex.unlock();
if (rs == -1)
{
printf("__________Can open to change to des imag_____________e\n");
return -1;
}
}
}
}
av_free_packet(&packet);
av_frame_unref(pFrame);
av_packet_unref(&packet);
avpicture_free(&picture);
return 1;
}
void ffmpeg_decoder::close_stream(){
/*if (pFrame)
av_free(&pFrame);*/
if (pCodecCtx)
avcodec_close(pCodecCtx);
if (pSwsCtx)
sws_freeContext(pSwsCtx);
avpicture_free(&picture);
if (pFormatCtx)
avformat_close_input(&pFormatCtx);
}
Below is the main thread which do the decoding.
I am using Qt for creating thread and do decoding
ffmpeg_decoder * ffmpeg = new ffmpeg_decoder();;
if(ffmpeg->initial(rtspURL)==0){
while (1) {
ffmpeg->h264Decodec();
//get frame and do processing right now it disabled, and still see the memory leak.
.......
if(stopFlg.load()==1)
break;
}
//close stream if break
ffmpeg->close_stream();
}
else {
ffmpeg->close_stream();
}
When I run 36 thread with different URL I can see the memory usage of the program increase over time.
I have used valgrind to detect the leak, and here is the relevant part of the log
This is the first memory leak location
=14402== by 0x692017F: av_malloc (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x692048D: av_mallocz (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x691915E: av_frame_alloc (in /usr/lib/x86_64-linux-gnu/libavutil-ffmpeg.so.54.31.100)
==14402== by 0x419663: ffmpeg_decoder::initial(QString&) (ffmpeg_decoder.cpp:24)
==14402== by 0x41ABEC: RTSP_Player_Object::run() (rtsp_player_object.cpp:15)
Another
==14402== 2,176 bytes in 16 blocks are indirectly lost in loss record 23,113 of 23,379
==14402== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14402== by 0x7780A4E: QImageData::create(unsigned char*, int, int, int, QImage::Format, bool, void (*)(void*), void*) (in /home/vapplica/Qt5.11.1/5.11.1/gcc_64/lib/libQt5Gui.so.5.11.1)
==14402== by 0x7780C30: QImage::QImage(unsigned char*, int, int, QImage::Format, void (*)(void*), void*) (in /home/vapplica/Qt5.11.1/5.11.1/gcc_64/lib/libQt5Gui.so.5.11.1)
==14402== by 0x419B21: ffmpeg_decoder::h264Decodec() (ffmpeg_decoder.cpp:96)
I have check the documentation and sample on ffmpeg site, and I think I am releasing the allocated memory, but still I can see the memory leak when I run the program.
Trying my hands on libgphoto2 library examples and while going through simple-capture.c file. Can i download foo.jpg captured image to a specified folder on my computer?
As far as i understood, in capture_to_file() camera_file_path.folder is the folder in which the file can be found on the camera. So open() should specify the host(computer) location. But nothing worked, i get following error:
You need to specify a folder starting with /store_xxxxxxxxx/
Am i missing something here? Any help would be appreciated, thanks!
I got this working.
Written small application for multiple cameras. Including main() for about question.
int main(int argc, char **argv)
{
CameraList *list;
Camera **cams;
int retval, count, i;
GPContext *context;
FILE *f;
char *data;
unsigned long size;
const char *name, *value;
/*
* Create context
*/
context = sample_create_context();
/*
* Setup Images DB directory.
*/
char* home = getenv("HOME");
if (home == NULL)
{
printf("Error: Unable to fetch home env! \n");
exit(1);
}
char* path = "/Desktop/mw/";
size_t len = strlen(home) + strlen(path) + 1;
char* imgdb = malloc(len);
if (imgdb == NULL)
{
printf("Error: Unable to malloc(). \n");
exit(1);
}
strcpy(imgdb, home);
strcat(imgdb, path);
directory_exists_or_create(imgdb);
/*
* Logs
*/
gp_log_add_func(GP_LOG_ERROR, errordumper, NULL);
/*
* Detect all the cameras that can be autodetected
*/
retval = gp_list_new(&list);
if (retval < GP_OK)
{
printf("Unable to create camera list.\n");
return 1;
}
count = sample_autodetect(list, context);
if (count < GP_OK)
{
printf("No cameras detected.\n");
return 1;
}
/*
* Now open all the cameras we autodetected for usage.
*/
printf("Number of cameras: %d\n", count);
cams = calloc(sizeof(Camera*), count);
for (i = 0; i < count; i++)
{
gp_list_get_name(list, i, &name);
gp_list_get_value(list, i, &value);
retval = sample_open_camera(&cams[i], name, value, context);
if (retval < GP_OK)
{
fprintf(stderr, "Camera %s on port %s failed to open\n", name, value);
}
}
if (argc > 0)
{
while ((++argv)[0])
{
if (argv[0][0] == '-')
{
switch (argv[0][1])
{
case 'h':
case 'H':
{
/* Now call a simple function in each of those cameras. */
for (i = 0; i < count; i++)
{
CameraText text;
char *owner;
retval = gp_camera_get_summary (cams[i], &text, context);
if (retval < GP_OK)
{
fprintf (stderr, "Failed to get summary.\n");
continue;
}
gp_list_get_name (list, i, &name);
gp_list_get_value (list, i, &value);
printf("%-30s %-16s\n", name, value);
printf("Summary:\n%s\n", text.text);
/* Query a simple string configuration variable. */
retval = get_config_value_string (cams[i], "owner", &owner, context);
if (retval >= GP_OK)
{
printf("Owner: %s\n", owner);
free (owner);
}
else
{
printf("Owner: No owner found.\n");
}
}
}
/* Graceful exit from the program */
goto exit_;;
default:
printf("Unknown option -%c\n\n", argv[0][1]);
break;
}
}
}
}
/* When I set GP_LOG_DEBUG instead of GP_LOG_ERROR above, I noticed that the
* init function seems to traverse the entire filesystem on the camera. This
* is partly why it takes so long.
* (Marcus: the ptp2 driver does this by default currently.)
*/
printf("Cameras init. Takes about 10 seconds each.\n");
for (i = 0; i < count; i++)
{
retval = gp_camera_init(cams[i], context);
if (retval != GP_OK)
{
printf(" Camera [%d] init failed with retval %d\n", i, retval);
exit (1);
}
}
printf(" ----------------\n");
printf(" Sampler is ready \n");
printf(" ----------------\n");
printf("Usage : \n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
char get_key;
char exit_key = 0;
char bcr_buf[128] = {0};
int hemispheres_counts = 0;
int rotar_steps = 0;
do
{
get_key = getchar();
switch (get_key)
{
// Gracefull Exit
case _ESC_:
exit_key = 1;
break;
// Manual insert mode
case 'i':
case 'I':
printf("ACTION: Type in the name.\n");
scanf("%128s", bcr_buf);
process:
press_enter();
printf("ACTION: Shall we start? press return key.\n");
press_enter();
hemispheres_counts = 0;
rotar_steps = 0;
char product_filename[256] = {0};
strcpy(product_filename, imgdb);
strcat(product_filename, bcr_buf);
if (directory_exists_or_create(product_filename))
{
printf("\n\n!!! ATTENTION: The product already exists !!!\n\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
while (hemispheres_counts < MAX_HEMISPHERES)
{
while (rotar_steps < MAX_ROTAR_STEPS)
{
for (i = 0; i < count; i++)
{
capture_to_memory(cams[i], context, (const char**)&data, &size);
char fname[64] = {0};
char mk_filename[256] = {0};
strcpy(mk_filename, product_filename);
snprintf(fname, sizeof(fname), "/%d-%d-%d.jpg", i, hemispheres_counts, rotar_steps);
strcat(mk_filename, fname);
printf("file name %s\n", mk_filename);
f = fopen(mk_filename, "wb");
if (f)
{
retval = fwrite (data, size, 1, f);
if (retval != size)
{
printf(" fwrite size %ld, written %d\n", size, retval);
}
fclose(f);
}
else
{
printf(" fopen *.jpg failed. %s\n", strerror(errno));
}
usleep(500*1000);
}
rotar_steps++;
}
rotar_steps = 0;
hemispheres_counts++;
if (hemispheres_counts < MAX_HEMISPHERES)
{
printf("Flip the product and hit 'RETURN' key\n");
press_enter(); // This expect some input from user, thats it.
printf("Started capturing other hemisphere!\n");
} else {
printf("Sampling Done for barcode: %s\n", bcr_buf);
printf(" -------------------------------------\n");
printf("\nEnter options:\n");
printf(" ESC - Exit the program\n");
printf(" i/I - Insert new product barcode manually\n");
#if defined(BARCODE_ENABLED)
printf(" b/B - Insert new product barcode using barcode-scanner\n");
#endif
break;
}
}
break;
}
} while (exit_key != 1);
exit_:
/*
* Release all the resources.
*/
printf("\nReleasing all the resources ... \n");
for (i = 0; i < count; i++)
{
gp_camera_exit(cams[i], context);
}
if (cams) {
free(cams);
}
free(imgdb);
#if defined(BARCODE_ENABLED)
close_bcr();
#endif
printf("Done.\n");
return 0;
}
I get an error when I use modbus_rtu_set_serial_mode. The error is thrown by ioctl saying bad file descriptor. After googling I found out that a dozen of people had problems with this, but sadly no solutions. If you have even the slightest clue what's going on, please at least set me in the right direction. I'm working in Ubuntu 14.04.1 LTS
#define MODBUS_RTU_RS232 0
#define MODBUS_RESPONSE_TIMEOUT_SEC 10
#define MODBUS_RESPONSE_TIMEOUT_USEC 0
//...
std::string mode = "RTU";
std::string port = "/dev/ttyO3";
std::string commInterface = "RS232";
int baudrate = 19200;
char parity = 'N';
int dataBit = 8;
int stopBit = 1;
int slaveAddress = 10;
modbus_t *mb;
//...
}
//function calling the modbus_rtu_set_serial_mode
//...
if(mode = "RTU"){
mb = modbus_new_rtu(port, baudrate, parity, dataBit, stopBit);
if(mb == NULL)
{
return false;
}
}
if(commInterface == "RS232"){
if(modbus_rtu_set_serial_mode(mb, MODBUS_RTU_RS232) < 0){
std::cout << "modbus_rtu_set_serial_mode failed, errMsg: "
<< modbus_strerror(errno); //Here it prints "Bad File Descriptor"
modbus_close(mb);
modbus_free(mb);
return false;
}
}
struct timeval old_response_timeout;
modbus_get_response_timeout(mb, &old_response_timeout);
struct timeval response_timeout;
response_timeout.tv_sec = MODBUS_RESPONSE_TIMEOUT_SEC;
response_timeout.tv_usec = MODBUS_RESPONSE_TIMEOUT_USEC;
modbus_set_response_timeout(mb, &response_timeout);
modbus_set_slave(mb, slaveAddress);
int connectSlave = modbus_connect(mb);
if (connectSlave < 0)
{
std::cout << "Slave error";
modbus_close(mb);
modbus_free(mb);
return false;
}
//...
modbus-rtu.c file
int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode)
{
if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) {
#if HAVE_DECL_TIOCSRS485
modbus_rtu_t *ctx_rtu = ctx->backend_data;
struct serial_rs485 rs485conf;
memset(&rs485conf, 0x0, sizeof(struct serial_rs485));
if (mode == MODBUS_RTU_RS485) {
rs485conf.flags = SER_RS485_ENABLED;
if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) {
return -1;
}
ctx_rtu->serial_mode |= MODBUS_RTU_RS485;
return 0;
} else if (mode == MODBUS_RTU_RS232) {
if (ioctl(ctx->s, TIOCSRS485, &rs485conf) < 0) {
return -1;
}
/*int status;
status |= TIOCM_RTS;
if (ioctl(ctx->s, TIOCMSET, &status) < 0) {
return -1;
}*/
ctx_rtu->serial_mode = MODBUS_RTU_RS232;
return 0;
}
#else
if (ctx->debug) {
fprintf(stderr, "This function isn't supported on your platform\n");
}
errno = ENOTSUP;
return -1;
#endif
}
/* Wrong backend and invalid mode specified */
errno = EINVAL;
return -1;
}
I am currently making a simple client and server but I have run into an issue. Part of the system is for the client to query about a local file on the server. The contents of that file must be then sent to the client. I am able to send all the text within a file to the client however it seems to be stuck in the read loop on the client. Below are the code spits for both the client and server that are meant to deal with this:
Client Code That Reads The Loop
else if(strcmp(commandCopy, get) == 0)
{
char *ptr;
int total = 0;
char *arguments[1024];
char copy[2000];
char * temp;
int rc;
strcpy(copy, command);
ptr = strtok(copy," ");
while (ptr != NULL)
{
temp = (char *)malloc(sizeof(ptr));
temp = ptr;
arguments[total] = temp;
total++;
ptr = strtok (NULL, " ");
}
if(total == 4)
{
if (strcmp(arguments[2], "-f") == 0)
{
printf("1111111111111");
send(sockfd, command, sizeof(command), 0 );
printf("sent %s\n", command);
memset(&command, '\0', sizeof(command));
cc = recv(sockfd, command, 2000, 0);
if (cc == 0)
{
exit(0);
}
}
else
{
printf("Here");
strcpy(command, "a");
send(sockfd, command, sizeof(command), 0 );
printf("sent %s\n", command);
memset(&command, '\0', sizeof(command));
cc = recv(sockfd, command, 2000, 0);
}
}
else
{
send(sockfd, command, sizeof(command), 0 );
printf("sent %s\n", command);
memset(&command, '\0', sizeof(command));
while ((rc = read(sockfd, command, 1000)) > 0)
{
printf("%s", command);
}
if (rc)
perror("read");
}
}
Server Code That Reads the File
char* getRequest(char buf[], int fd)
{
char * ptr;
char results[1000];
int total = 0;
char *arguments[1024];
char data[100];
FILE * pFile;
pFile = fopen("test.txt", "r");
ptr = strtok(buf," ");
while (ptr != NULL)
{
char * temp;
temp = (char *)malloc(sizeof(ptr));
temp = ptr;
arguments[total] = temp;
total++;
ptr = strtok (NULL, " ");
}
if(total < 2)
{
strcpy(results, "Invaild Arguments \n");
return results;
}
if(pFile != NULL)
{
while(fgets(results, sizeof(results), pFile) != NULL)
{
//fputs(mystring, fd);
write(fd,results,strlen(results));
}
}
else
{
printf("Invalid File or Address \n");
}
fclose(pFile);
return "End of File \0";
}
Server Code to execute the command
else if(strcmp(command, "get") == 0)
{
int pid = fork();
if (pid ==-1)
{
printf("Failed To Fork...\n");
return-1;
}
if (pid !=0)
{
wait(NULL);
}
else
{
char* temp;
temp = getRequest(buf, newsockfd);
strcpy(buf, temp);
send(newsockfd, buf, sizeof(buf), 0 );
exit(1);
}
}
The whole else if clause in the client code is a bit large for a function, let alone a part of a function as it presumably is. The logic in the code is ... interesting. Let us dissect the first section:
else if (strcmp(commandCopy, get) == 0)
{
char *ptr;
int total = 0;
char *arguments[1024];
char *temp;
ptr = strtok(copy, " ");
while (ptr != NULL)
{
temp = (char *)malloc(sizeof(ptr));
temp = ptr;
arguments[total] = temp;
total++;
ptr = strtok(NULL, " ");
}
I've removed immaterial declarations and some code. The use of strtok() is fine in context, but the memory allocation is leaky. You allocate enough space for a character pointer, and then copy the pointer from strtok() over the only pointer to the allocated space (thus leaking it). Then the pointer is copied to arguments[total]. The code could, therefore, be simplified to:
else if (strcmp(commandCopy, get) == 0)
{
char *ptr;
int total = 0;
char *arguments[1024];
ptr = strtok(copy, " ");
while (ptr != NULL)
{
arguments[total++] = ptr;
ptr = strtok(NULL, " ");
}
Nominally, there should be a check that you don't overflow the arguments list, but since the original limits the string to 2000 characters, you can't have more than 1000 arguments (all single characters separated by single spaces).
What you have works - it achieves the same assignment the long way around, but it leaks memory prodigiously.
The main problem seems to be that the server sends all the contents, but it doesn't close the socket, so the client has no way of knowing the server's done. If you close the socket after you finish sending the data (or just call shutdown()), then the client's read() will return 0 when it finishes reading the data.
FWIW, there are lots of other problems with this code:
getRequest: you call malloc but never free. In fact, the return value is thrown away.
Why bother forking if you're just going to wait() on the child?
You probably want to use strlcpy instead of strpcy to avoid buffer overruns.