BSD sockets on Mac
So now and then I need to have send some data from one application to another one. Having a simple test server around which you easily debug is very nice to have. Therefore I past this snippet of code which creates a tcp server which working on unix/linux. It's purpose is to be used as a snippet for a test server, not for a fully fledged server. I'm working on some demo applications for a iPhone class I'll be teaching which involve communication with a server. Stay tuned for more info on this! I'm using the Poco threading classes (which you can remove if you want to)
LEDServer.h
#ifndef LEDSERVERH #define LEDSERVERH #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/select.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> #include "Poco/Thread.h" #include <vector> #include <map> using std::vector; using std::map; class LEDClient; class LEDServer : public Poco::Runnable { public: LEDServer(); ~LEDServer(); void start(); void run(); private: int server_socket; int server_port; struct sockaddr_in server_addr; Poco::Thread thread; map<int, LEDClient*> clients; }; #endif
LEDServer.cpp
#include "LEDServer.h" #include "LEDClient.h" LEDServer::LEDServer() :server_socket(0) ,server_port(8888) { } LEDServer::~LEDServer() { thread.join(); } void LEDServer::start() { thread.start(*this); } void LEDServer::run() { server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(server_socket == -1) { printf("Can't create server socket\n"); } int result = 0; int val; result = setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); if(result < 0) { printf("Cannot reuse address\n"); exit(1); } // bind. bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(8888); result = bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)); if(result != 0) { printf("Cannot bind...\n"); exit(1); } // listen result = listen(server_socket, 5); if(result < 0) { printf("Cannot set listen mode to socket\n"); close(server_socket); exit(1); } // some sets fd_set socket_readset, test_set; FD_ZERO(&socket_readset); FD_SET(server_socket, &socket_readset); while(true) { // get notified by readset. test_set = socket_readset; result = select(FD_SETSIZE, &test_set, NULL, NULL, NULL); if(result < 1) { printf("Server error\n"); exit(1); } for(int i = 0; i < FD_SETSIZE; ++i) { if(FD_ISSET(i, &test_set)) { if(i == server_socket) { // listen for a new connection. struct sockaddr_in client_addr = {0}; int child_socket = 0; int client_addr_len = sizeof(client_addr); child_socket = accept(server_socket, (struct sockaddr*)&client_addr, (socklen_t*) &client_addr_len); if(child_socket == -1) { printf("Cannot accept connections\n"); close(server_socket); exit(1); } // store our new client. FD_SET(child_socket, &socket_readset); LEDClient* lc = new LEDClient(child_socket); clients.insert(std::pair<int,LEDClient*>(child_socket, lc)); } else { map<int, LEDClient*>::iterator it = clients.find(i); if(it != clients.end()) { it->second->readFromSocket(); } } } } } // clean up.. map<int, LEDClient*>::iterator it = clients.begin(); while(it != clients.end()) { delete it->second; ++it; } }
LEDClient.h
#ifndef LEDCLIENTH #define LEDCLIENTH #include <iostream> #include <vector> using namespace std; class LEDClient { public: LEDClient(int clientSock); void readFromSocket(); int sock; vector<char> buffer; }; #endif
LEDClient.cpp
#include "LEDClient.h" LEDClient::LEDClient(int clientSock) :sock(clientSock) { } void LEDClient::readFromSocket() { char tmp_buf[512]; ssize_t bytes_read = read(sock, tmp_buf, 512); std::copy(tmp_buf, tmp_buf+bytes_read, std::back_inserter(buffer)); // show what we got so far. cout << "Now in buffer (" << buffer.size() << ") = " ; for(int i = 0; i < buffer.size(); ++i) { cout << buffer[i]; } cout << endl; }