Here is an example of echo TCP server from libevent book.
How can I modify it to close a socket after each write. I know that I can close a socket connection by calling bufferevent_free(), but I don't understand how use it to close connection every time I send an echo to the socket.
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
static void
echo_read_cb(struct bufferevent *bev, void *ctx)
{
/* This callback is invoked when there is data to read on bev. */
struct evbuffer *input = bufferevent_get_input(bev);
struct evbuffer *output = bufferevent_get_output(bev);
/* Copy all the data from the input buffer to the output buffer. */
evbuffer_add_buffer(output, input);
}
static void
echo_event_cb(struct bufferevent *bev, short events, void *ctx)
{
if (events & BEV_EVENT_ERROR)
perror("Error from bufferevent");
if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
bufferevent_free(bev);
}
}
static void
accept_conn_cb(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr *address, int socklen,
void *ctx)
{
/* We got a new connection! Set up a bufferevent for it. */
struct event_base *base = evconnlistener_get_base(listener);
struct bufferevent *bev = bufferevent_socket_new(
base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, echo_read_cb, NULL, echo_event_cb, NULL);
bufferevent_enable(bev, EV_READ|EV_WRITE);
}
static void
accept_error_cb(struct evconnlistener *listener, void *ctx)
{
struct event_base *base = evconnlistener_get_base(listener);
int err = EVUTIL_SOCKET_ERROR();
fprintf(stderr, "Got an error %d (%s) on the listener. "
"Shutting down.\n", err, evutil_socket_error_to_string(err));
event_base_loopexit(base, NULL);
}
int
main(int argc, char **argv)
{
struct event_base *base;
struct evconnlistener *listener;
struct sockaddr_in sin;
int port = 9876;
if (argc > 1) {
port = atoi(argv[1]);
}
if (port<=0 || port>65535) {
puts("Invalid port");
return 1;
}
base = event_base_new();
if (!base) {
puts("Couldn't open event base");
return 1;
}
/* Clear the sockaddr before using it, in case there are extra
* platform-specific fields that can mess us up. */
memset(&sin, 0, sizeof(sin));
/* This is an INET address */
sin.sin_family = AF_INET;
/* Listen on 0.0.0.0 */
sin.sin_addr.s_addr = htonl(0);
/* Listen on the given port. */
sin.sin_port = htons(port);
listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
(struct sockaddr*)&sin, sizeof(sin));
if (!listener) {
perror("Couldn't create listener");
return 1;
}
evconnlistener_set_error_cb(listener, accept_error_cb);
event_base_dispatch(base);
return 0;
}
From my understanding of documentation - you should put bufferevent_free(bev); at the end of echo_event_cb() function, this should close the connection after echoing user data back w/o waiting the client to close it. This should work this way till you use BEV_OPT_CLOSE_ON_FREE when creating bev buffer event.
Related
I'm new to c++ and need help.
I use an UDP server to receive structure however i have problem to read it , the client send a structure I call : ChannAccessReq so the structure is send and the server receive it with RECVFROM and I use a general structure by reading the header (H1) of the struct only and then i do a read when a condition is fullfill with a more precise structure (temp2) for the buffer. However the client need to send the message twice , the first time it goes until recvfrom and the second it reach read() (i think) I tried all the day and wonder if its the size of the buffer ?
I think the most sensitive part is in the server with the recvfrom() who have a struct different from the read() just after..
I hope it's clear!
here is the server :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
#include <iostream>
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct IntMsgHeaderType {
uint8_t code ; // Code message7
uint8_t bourrage ; // Octet de bourrage
uint16_t ParamLength; // Longueur eventuel données complémentaires
} HeaderInt;
typedef struct TextMessage //TESTTESTTEST
{
HeaderInt H; // Code message7
};
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in echoServAddr; /* Local address */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int cliAddrLen; /* Length of incoming message */
unsigned short echoServPort; /* Server port */
int recvMsgSize; /* Size of received message */
struct TextMessage * temp = (TextMessage *)malloc(sizeof(struct TextMessage));
HeaderInt *H1 =(HeaderInt *)malloc(104+sizeof(HeaderInt));
ChanAccesReq *temp2=(ChanAccesReq *)malloc(sizeof(ChanAccesReq));
if (!argv[1]) {
fprintf(stderr,"no port number provided");
exit(1);
}
echoServPort = atoi(argv[1]); /* First arg: local port */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct local address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
for (;;) /* Run forever */
{
cliAddrLen = sizeof(echoClntAddr);
int nbrOctet;
if (recvfrom(sock, H1, sizeof(*H1), 0,(struct sockaddr *) &echoClntAddr, &cliAddrLen)>0 && H1->code==1){
//read(sock,H1,sizeof(*H1));
std::cout<<"taille nbrOctet : "<<nbrOctet<<'\n';
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
read(sock, temp2, sizeof(*temp2));
//read(sock,temp2,sizeof(*temp2))>0;
std::cout<<unsigned(temp2->P.linkAddr)<<'\n';
};
}
close(sock);
return 0;
}
and here the client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct {
char transMode ;
uint8_t linkAddr;
} ChanAccessReqParam;
typedef struct {
HeaderInt H;
ChanAccessReqParam P;
} ChanAccesReq ;
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned short echoServPort; /* Echo server port */
unsigned int fromSize; /* In-out of address size for recvfrom() */
char *servIP; /* IP address of server */
int structLen; /* Length of string to echo */
int respStringLen; /* Length of received response */
if (!argv[1]) {
fprintf(stderr,"No server IP sepcified at arg 1\n");
exit(1);
}
else if (!argv[2]) {
fprintf(stderr,"No port Number Sepcified at arg 2\n");
exit(2);
}
ChanAccesReq test { 1 ,1,0,'c',15};
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
echoServPort = atoi(argv[2]); /* Use given port, if any */
/* Create a datagram/UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet addr family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
int tempint = 0;
tempint = sendto(sock, (ChanAccesInd*)&test, 10+(sizeof(test)), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr));
if (tempint == -1 ) {
printf("Sent struct size: %d\n", tempint);
DieWithError("sendto() sent a different number of bytes than expected\n");
}
close(sock);
exit(0);
}
Thank you for your help
In C++ you have to define the type of the parameters.
As I deduced from the calling place, it should be int and bool.
int GesCanSlotSendTimeInd( int subscIPAddr , bool TransModeFlash){
return 0;
}
Also it is possible to use const qualifier, but you also need the type.
int GesCanSlotSendTimeInd( const int& subscIPAddr , const bool& TransModeFlash){
return 0;
}
For further info please look at cpp reference
You need to use non-blocking mode to poll for recvfrom and sendto at the same time. See here for more details.
int main(int argc, const char** argv) {
setvbuf(stdout, NULL, _IONBF, 0);
int portnum = 9988;
if (argc >= 2) {
portnum = atoi(argv[1]);
}
printf("Listening on port %d\n", portnum);
int sockfd = listen_inet_socket(portnum);
struct sockaddr_in peer_addr;
socklen_t peer_addr_len = sizeof(peer_addr);
int newsockfd = accept(sockfd, (struct sockaddr*)&peer_addr, &peer_addr_len);
if (newsockfd < 0) {
perror_die("ERROR on accept");
}
report_peer_connected(&peer_addr, peer_addr_len);
// Set nonblocking mode on the socket.
int flags = fcntl(newsockfd, F_GETFL, 0);
if (flags == -1) {
perror_die("fcntl F_GETFL");
}
if (fcntl(newsockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror_die("fcntl F_SETFL O_NONBLOCK");
}
while (1) {
uint8_t buf[1024];
printf("Calling recv...\n");
int len = recv(newsockfd, buf, sizeof buf, 0);
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
usleep(200 * 1000);
continue;
}
perror_die("recv");
} else if (len == 0) {
printf("Peer disconnected; I'm done.\n");
break;
}
printf("recv returned %d bytes\n", len);
}
close(newsockfd);
close(sockfd);
return 0;
}
"A couple of notable differences from the blocking version:
The newsockfd socket returned by accept is set to nonblocking mode by calling fcntl.
When examining the return status of recv, we check whether errno is set to a value saying that no data is available for receiving. In this case we just sleep for 200 milliseconds and continue to the next iteration of the loop."
You can still send() and recvfrom() on the same socket since that you dont really need 2 differents process if that's what you need
I want to use sockets inside my network simulation done with Omnet++, i am getting a collision of method name between:
send() method of Socket.
send() method defined by Omnet++, that allow
exchange of msg between simulation modules.
The compiler recognize only send() method defined by Omnet++.
How can i resolve it ?
Thank you,
EDIT
In order to make it more clear, i will past a copy of my code:
GeoTraCIMobility.cc (CPP Code)
#include <limits>
#include <iostream>
#include <sstream>
//#include <cstring> // Needed for memset
//#include <sys/socket.h> // Needed for the socket functions
//#include <netdb.h> // Needed for the socket functions
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "mobility/geoTraCI/GeoTraCIMobility.h"
Define_Module(GeoTraCIMobility);
namespace {
const double MY_INFINITY = (std::numeric_limits<double>::has_infinity ? std::numeric_limits<double>::infinity() : std::numeric_limits<double>::max());
double roadIdAsDouble(std::string road_id) {
std::istringstream iss(road_id);
double d;
if (!(iss >> d)) return MY_INFINITY;
return d;
}
}
void GeoTraCIMobility::Statistics::initialize()
{
firstRoadNumber = MY_INFINITY;
startTime = simTime();
totalTime = 0;
stopTime = 0;
minSpeed = MY_INFINITY;
maxSpeed = -MY_INFINITY;
totalDistance = 0;
totalCO2Emission = 0;
}
//OTHERS FUNCTIONS
// Function that create a socket and send data
void GeoTraCIMobility::requestingFromPyServer()
{
std::string HOST = "127.0.0.1";
int PORT = 19999;
int MAX_BUFFER = 1024;
int connectionFd, rc, index = 0, limit = MAX_BUFFER;
struct sockaddr_in servAddr, localAddr;
char buffer[MAX_BUFFER+1];
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(PORT);
servAddr.sin_addr.s_addr = inet_addr(HOST.c_str());
// Create socket
connectionFd = socket(AF_INET, SOCK_STREAM, 0);
/* bind any port number */
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(0);
rc = bind(connectionFd,
(struct sockaddr *) &localAddr, sizeof(localAddr));
// Connect to Server
connect(connectionFd,
(struct sockaddr *)&servAddr, sizeof(servAddr));
// Send request to Server
std::string req= "ShortestPath_297162704_82660198";
sprintf( buffer, "%s", req.c_str() );
// UNRECOGNIZED SEND METHOD
send(connectionFd, buffer, strlen(buffer), 0 );
// UNRECOGNIZED SEND METHOD
close(connectionFd);
printf("Client closed.\n");
}
GeoTraCIMobility.cc inherits from cSimpleModule the following send methods:
cSimpleModule.h
/**
* Sends a message through the gate given with its ID.
*/
int send(cMessage *msg, int gateid) {return sendDelayed(msg, SIMTIME_ZERO, gateid);}
/**
* Sends a message through the gate given with its name and index
* (if multiple gate).
*/
int send(cMessage *msg, const char *gatename, int gateindex=-1) {return sendDelayed(msg, SIMTIME_ZERO, gatename, gateindex);}
/**
* Sends a message through the gate given with its pointer.
*/
int send(cMessage *msg, cGate *outputgate) {return sendDelayed(msg, SIMTIME_ZERO, outputgate);}
Use ::send(...) to access the global function in an OMNeT++ model. Otherwise the send() method inhertited from the cSimpleModule will be called.
I have a questions about using fcntl and sigaction to receive a UDP packet asynchronously. In my program I have two sources of UDP traffic that I would like to monitor. I have set up two sockets for the traffic and used this tutorial to set the file descriptor to trigger a sigaction whenever I receive a UDP packet.
This works fine with only one source, but when I add the other source it will trigger only one of the handlers whenever either file descriptor receives a packet.
Here is a short program demonstrating the behavior:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int done;
int a_fd;
int b_fd;
int recv_dgram(int fd, char* dgram, int size)
{
struct sockaddr_in addr;
int fromlen = sizeof(addr);
return recvfrom(fd, dgram, size, 0, (struct sockaddr*)&addr, (socklen_t*)&fromlen);
}
void a_handler(int signum)
{
char dgram[256];
int size = recv_dgram(a_fd, dgram, 256);
printf("a recieve size: %d\n", size);
}
void b_handler(int signum)
{
char dgram[256];
int size = recv_dgram(b_fd, dgram, 256);
printf("b recieve size: %d\n", size);
}
void sig_handle(int signum)
{
done = 1;
}
int init_fd(int port, const char* group, const char* interface)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if(fd < 0) {
return -1;
}
int reuse = 1;
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0) {
close(fd);
return -1;
}
if(fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
close(fd);
return -1;
}
struct sockaddr_in addr;
memset((char*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(fd, (struct sockaddr*)&addr, sizeof(addr))) {
close(fd);
return -1;
}
struct ip_mreq mcast_group;
mcast_group.imr_multiaddr.s_addr = inet_addr(group);
mcast_group.imr_interface.s_addr = inet_addr(interface);
if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mcast_group, sizeof(mcast_group))) {
close(fd);
return -1;
}
return fd;
}
int main(int argc, const char* argv[])
{
done = 0;
signal(SIGINT, sig_handle);
signal(SIGTERM, sig_handle);
// make sockets and sigactions
a_fd = init_fd([a port], [a multicast group], [a interface]);
if(a_fd < 0) {
return -1;
}
pid_t pid = getpid();
int a_flags = fcntl(a_fd, F_GETFL);
fcntl(a_fd, F_SETFL, a_flags | O_ASYNC);
struct sigaction a_sa;
a_sa.sa_flags = 0;
a_sa.sa_handler = a_handler;
sigemptyset(&a_sa.sa_mask);
sigaction(SIGIO, &a_sa, NULL);
fcntl(a_fd, F_SETOWN, pid);
fcntl(a_fd, F_SETSIG, SIGIO);
b_fd = init_fd([b port], [b multicast group], [b interface]);
if(b_fd < 0) {
close(a_fd);
return -1;
}
int b_flags = fcntl(b_fd, F_GETFL);
fcntl(b_fd, F_SETFL, b_flags | O_ASYNC);
struct sigaction b_sa;
b_sa.sa_flags = 0;
b_sa.sa_handler = b_handler;
sigemptyset(&b_sa.sa_mask);
sigaction(SIGIO, &b_sa, NULL);
fcntl(b_fd, F_SETOWN, pid);
fcntl(b_fd, F_SETSIG, SIGIO);
printf("start\n");
while(!done) { pause(); }
printf("done\n");
close(a_fd);
close(b_fd);
return 0;
}
I can compile this with (you can compile using gcc too):
g++ -c test.cpp
g++ -o test test.o
I'm using g++ 4.6.3 on Ubuntu 12.04 LTS.
When I run this program with two sources of UDP data, b_handler gets triggered when either file descriptors has a packet available. So it will print "b received size: -1" whenever a_handler should receive a packet. a_handler never gets called.
I suspect that this is because getpid() will return the same value for both of them so one of the sigaction handler will be overwritten.
Is there any way I can have these two handlers trigger independent of each other?
Thanks for the help.
Use two different signals, say SIGIO and SIGUSR1.
fcntl(descriptor, SETSIG, signal_desired);
I'm trying to understand this Libevent c++ code I got from this page.
I'm a bit confused - am I correct to think that this code might have memory leaks?
It seems like ConnectionData pointer is created in on_connect() callback, but delete() is only called on bad read or after write is complete.
What if connection was accept()ed - but there were no reads or writes? so is that pointer just stays in daemon memory?
#include <event.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
// Read/write buffer max length
static const size_t MAX_BUF = 512;
typedef struct {
struct event ev;
char buf[MAX_BUF];
size_t offset;
size_t size;
} ConnectionData;
void on_connect(int fd, short event, void *arg);
void client_read(int fd, short event, void *arg);
void client_write(int fd, short event, void *arg);
int main(int argc, char **argv)
{
// Check arguments
if (argc < 3) {
std::cout << "Run with options: <ip address> <port>" << std::endl;
return 1;
}
// Create server socket
int server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock == -1) {
std::cerr << "Failed to create socket" << std::endl;
return 1;
}
sockaddr_in sa;
int on = 1;
char * ip_addr = argv[1];
short port = atoi(argv[2]);
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
sa.sin_addr.s_addr = inet_addr(ip_addr);
// Set option SO_REUSEADDR to reuse same host:port in a short time
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
std::cerr << "Failed to set option SO_REUSEADDR" << std::endl;
return 1;
}
// Bind server socket to ip:port
if (bind(server_sock, reinterpret_cast<const sockaddr*>(&sa), sizeof(sa)) == -1) {
std::cerr << "Failed to bind server socket" << std::endl;
return 1;
}
// Make server to listen
if (listen(server_sock, 10) == -1) {
std::cerr << "Failed to make server listen" << std::endl;
return 1;
}
// Init events
struct event evserver_sock;
// Initialize
event_init();
// Set connection callback (on_connect()) to read event on server socket
event_set(&evserver_sock, server_sock, EV_READ, on_connect, &evserver_sock);
// Add server event without timeout
event_add(&evserver_sock, NULL);
// Dispatch events
event_dispatch();
return 0;
}
// Handle new connection {{{
void on_connect(int fd, short event, void *arg)
{
sockaddr_in client_addr;
socklen_t len = 0;
// Accept incoming connection
int sock = accept(fd, reinterpret_cast<sockaddr*>(&client_addr), &len);
if (sock < 1) {
return;
}
// Set read callback to client socket
ConnectionData * data = new ConnectionData;
event_set(&data->ev, sock, EV_READ, client_read, data);
// Reschedule server event
event_add(reinterpret_cast<struct event*>(arg), NULL);
// Schedule client event
event_add(&data->ev, NULL);
}
//}}}
// Handle client request {{{
void client_read(int fd, short event, void *arg)
{
ConnectionData * data = reinterpret_cast<ConnectionData*>(arg);
if (!data) {
close(fd);
return;
}
int len = read(fd, data->buf, MAX_BUF - 1);
if (len < 1) {
close(fd);
delete data;
return;
}
data->buf[len] = 0;
data->size = len;
data->offset = 0;
// Set write callback to client socket
event_set(&data->ev, fd, EV_WRITE, client_write, data);
// Schedule client event
event_add(&data->ev, NULL);
}
//}}}
// Handle client responce {{{
void client_write(int fd, short event, void *arg)
{
ConnectionData * data = reinterpret_cast<ConnectionData*>(arg);
if (!data) {
close(fd);
return;
}
// Send data to client
int len = write(fd, data->buf + data->offset, data->size - data->offset);
if (len < data->size - data->offset) {
// Failed to send rest data, need to reschedule
data->offset += len;
event_set(&data->ev, fd, EV_WRITE, client_write, data);
// Schedule client event
event_add(&data->ev, NULL);
}
close(fd);
delete data;
}
//}}}
The documentation for event_set says that the only valid event types are EV_READ or EV_WRITE, but the callback will be invoked with EV_TIMEOUT, EV_SIGNAL, EV_READ, or EV_WRITE. The documentation is not clear, but I expect the read callback will be invoked when the socket is closed by the client. I expect the delete in the failure branch in client_read will handle this situation.
Note that that is only the case if the client sends a FIN or RST packet. A client could establish a connection and leave it open forever. For this reason, this code should be modified to have a timeout (perhaps via event_once) and require the client send a message within that timeout.
I'm running out of file descriptors when my program can't connect another host. The close() system call doesn't work, the number of open sockets increases. I can se it with
cat /proc/sys/fs/file-nr
Print from console:
connect: No route to host
close: Bad file descriptor
connect: No route to host
close: Bad file descriptor
..
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <iostream>
using namespace std;
#define PORT 1238
#define MESSAGE "Yow!!! Are we having fun yet?!?"
#define SERVERHOST "192.168.9.101"
void
write_to_server (int filedes)
{
int nbytes;
nbytes = write (filedes, MESSAGE, strlen (MESSAGE) + 1);
if (nbytes < 0)
{
perror ("write");
}
}
void
init_sockaddr (struct sockaddr_in *name,
const char *hostname,
uint16_t port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);
if (hostinfo == NULL)
{
fprintf (stderr, "Unknown host %s.\n", hostname);
}
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
}
int main()
{
for (;;)
{
sleep(1);
int sock;
struct sockaddr_in servername;
/* Create the socket. */
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket (client)");
}
/* Connect to the server. */
init_sockaddr (&servername, SERVERHOST, PORT);
if (0 > connect (sock,
(struct sockaddr *) &servername,
sizeof (servername)))
{
perror ("connect");
sock = -1;
}
/* Send data to the server. */
if (sock > -1)
write_to_server (sock);
if (close (sock) != 0)
perror("close");
}
return 0;
}
Fix:
if (0 > connect (sock,
(struct sockaddr *) &servername,
sizeof (servername)))
{
perror ("connect");
}
else
write_to_server (sock);
if (close (sock) != 0)
perror("close");
It looks like the problem is in the structure of your program. Every time through your infinite loop, you're creating a new socket. I'd suggest moving this out of the loop and re-using it.
If you'd like to just fix the way you're doing it now though, use close inside the "connect" failed if statement you have now. The descriptor is allocated by the 'socket' call and only connected with the 'connect' call. By setting your 'sock' variable to -1, you're throwing away the descriptor allocated by 'socket'. Call close, then set it to -1 and you should be set.