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.
Related
I can't receive message in multicast by my server however the sending is good I think, I supposed I messed with the IP's but don't know how to solve this.
Here is my testClient:
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <mutex>
#include <thread>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
struct in_addr localInterface;
struct sockaddr_in groupSock;
socklen_t groupSockLength;
int sd;
uint8_t databuf[5000] ;
int datalen = sizeof(databuf);
std::ofstream MyFile("TestAppliMsgReceive.txt");
ssize_t resRecv;
int main (int argc, char *argv[ ])
{
/* Create a datagram socket on which to send. */
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd < 0)
{
perror("Opening datagram socket error");
exit(1);
}
else
std::cout<<"Opening the datagram socket...OK.\n"<<std::endl;
/* Initialize the group sockaddr structure with a */
/* group address of 225.1.1.1 and port 5555. */
memset((char *) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("224.10.1.0");
groupSock.sin_port = htons(50000);
localInterface.s_addr = inet_addr("10.16.2.1");
if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0)
{
perror("Setting local interface error");
exit(1);
}
else
std::cout<<"Setting the local interface...OK\n"<<std::endl;
/* Send a message to the multicast group specified by the*/
/* groupSock sockaddr structure. */
if(sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0)
{perror("Sending datagram message error");}
else
std::cout<<"Sending datagram message...OK\n"<<std::endl;
while(1){
std::cout<<"Which kind of message do you want to send?"<<std::endl;
std::cout<<" [1] Custom message "<<std::endl;;
int choice;
std::cin>>choice;
if (choice==1) {
std::cout<<"enter msg\n";
std::cin>>databuf;
datalen = sizeof(databuf);
sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock));
}
}
return 0;
}
and here the server side, Maybe the problem is more here than in the client:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <string>
#include <list>
#include <mutex>
#include <thread>
//-------------------------------------------------------------------------------------------------
// Definition of variables common to all functions in the AppliMsg thread
//-------------------------------------------------------------------------------------------------
static char logInfoText[LOG_TEXT_SIZE]; // Text buffer for supervision log
static int localSockDesc; // Descriptor of the socket to the client application
static struct sockaddr_in localSockAddr; // IP address and port binded to the AppliMsg socket
static struct sockaddr_in mcastSockAddr; // Destination multicast address and port
//-------------------------------------------------------------------------------------------------
// Init of AppliMsg thread
//-------------------------------------------------------------------------------------------------
void AppliMsgInit()
{
std::string stgNetCastAddr; // Netcast IP address as a string
std::string stgNeighCastAddr; // Neighbourcast IP address as a string
std::string stgLocalIpAddr; // Ethernet interface IP address as a string
uint16_t localPortNum; // Port number of the Ethernet interface
struct ip_mreq ipMcast; // Multicast configuration
unsigned int numMcastTtl; // TTL definition
int sockFlags; // Flags of the socket
// Destination multicast address and port
mcastSockAddr.sin_family=AF_INET;
mcastSockAddr.sin_addr.s_addr=inet_addr("224.10.2.1");
mcastSockAddr.sin_port=htons(50000);
// Create the socket
localSockDesc = socket(AF_INET, SOCK_DGRAM, 0);
// Configure the socket for multicast capability and non-blocking reception
numMcastTtl = MCAST_TTL;
setsockopt(localSockDesc , IPPROTO_IP, IP_MULTICAST_TTL, (char *)&numMcastTtl, sizeof(numMcastTtl));
sockFlags = fcntl(localSockDesc, F_GETFL);
fcntl(localSockDesc, F_SETFL, sockFlags | O_NONBLOCK);
// Bind the Ethernet interface IP address and port to the socket
localSockAddr.sin_family=AF_INET;
localSockAddr.sin_addr.s_addr=inet_addr("10.16.2.1");
// localSockAddr.sin_addr.s_addr=INADDR_ANY; //SIMDEBUG
localSockAddr.sin_port=htons(50000);
// Bind the Ethernet IP address to the socket
if (bind(localSockDesc,(struct sockaddr *) &localSockAddr,sizeof(localSockAddr)) < 0)
{
// Error case
}
// Subscribe to the multicast server
ipMcast.imr_multiaddr.s_addr = inet_addr("224.10.2.1");
ipMcast.imr_interface.s_addr = inet_addr("10.16.2.1");
setsockopt(localSockDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ipMcast, sizeof(ipMcast));
}
//-------------------------------------------------------------------------------------------------
// Main function of the AppliMsg thread
//-------------------------------------------------------------------------------------------------
int AppliMsgWait()
{
std::string stgLocalIpAddr;
std::string stgNetCastAddr; // Netcast IP address as a string
std::string stgNeighCastAddr; // Neighbourcast IP address as a string
struct ip_mreq ipMcast; // Multicast configuration
// Main loop to process events from the simulated channel and the client application
while (1)
{
// Check the update flag in the Configuration Context
if (objConfigCtx.ConfigCtxGetFlagChangeAddr_()==true)
{
// Update the multicast configuration of the socket
ipMcast.imr_multiaddr.s_addr = inet_addr("224.10.1.0");
ipMcast.imr_interface.s_addr = inet_addr("10.16.2.1");
setsockopt(localSockDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ipMcast, sizeof(ipMcast));
}
// Check the presence and receive of a message from the client application
AppliMsgRecvSCOM();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return 1;
}
//-------------------------------------------------------------------------------------------------
// Check the presence and receive of a message from the client application
//-------------------------------------------------------------------------------------------------
void AppliMsgRecvSCOM()
{
struct sockaddr_in sourceSockAddr; // Sender IP address
socklen_t sourceSockAddrLength; // Temporary structure length
stcDataTransmIndT msgDataTransmInd; // Structure of the internal message in the list
ssize_t resRecv; // Value returned by recv()
sourceSockAddrLength = sizeof(sourceSockAddr);
// Non-blocking receive for an application message sent by SCOM
resRecv=recvfrom(localSockDesc,msgDataTransmInd.msgData,sizeof(msgDataTransmInd.msgData),0,
(struct sockaddr *) &sourceSockAddr,&sourceSockAddrLength);
else if (resRecv > 0)
{
// An application message is received:
}
}
And I think the focused part is about the IP address I used.
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
Im trying to send an Image with sockets from the server to the client, but for some reason im losing a lot of data.
this is my server:
#include <opencv2/imgcodecs.hpp>
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <string>
#define PORT 8080
using namespace cv;
using namespace std;
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
Mat image = cv::imread("Rio.jpg",IMREAD_COLOR); //BGR
std::vector< uchar > buf;
cv::imencode(".jpg",image,buf);
cerr << send(new_socket , buf.data() , buf.size(),0);
cerr << buf.data();
return 0;
}
The output of this file is:
562763����
562763 should be the size of data that is send to the client and ���� should be the data.
This is my Client:
#include <opencv2/imgcodecs.hpp>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <netinet/in.h>
#include <iostream>
#define PORT 8080
using namespace std;
using namespace cv;
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
int l = 0;
std::string data = "";
do{
data += buffer;
l += strlen(buffer);
valread = read( sock , buffer, 1024);
}while(valread != 0);
cerr << l;
char* c = const_cast<char*>(data.c_str());
std::vector<uchar> vec(c,c+l);
Mat image2 = cv::imdecode(vec, 1);
// cv::imwrite("test22.jpg",image2);
return 0;
}
The output i get is:
87567Corrupt JPEG data: 175 extraneous bytes before marker 0xec
87567 should be the size of the data received and because there is data missing the jpeg cant be created
When im sending a message like "This is a test" the full text is received by the client.
You have two major flaws, one which could lead to an infinite loop, and one which leads to the problem you experience:
The infinite loop problem will happen if read fails in the client and it returns -1. -1 != 0, and then read will continue to read -1 forever.
The second and main problem is that you treat the data you send between the programs a strings which it is not. A "string" is a null-terminated (i.e. zero-terminated) sequence of characters, your image is not that. In fact, it might even contain embedded zeros inside the data which will give you invalid data in the middle as well.
To solve both problem I suggest you change the reading loop (and the variables used) to something like this:
uchar buffer[1024];
ssize_t read_result;
std::vector<uchar> data;
// While there's no error (read returns -1) or the connection isn't
// closed (read returns 0), continue to append the received data
// into the vector
while ((read_result = read(sock, buffer, sizeof buffer)) > 0)
{
// No errors, no closed connection
// Append the new data (and only the new data) at the end of the vector
data.insert(end(data), buffer, buffer + read_result);
}
After this loop, and if read_result == 0, then data should contain only the data that was sent. And all of it.
In your client you are using buffer before you have read anything to it. You also are assuming that it is null terminated.
Something like this seems better
std::string data = "";
for (;;)
{
valread = read( sock , buffer, 1024);
if (valread <= 0)
break;
data.append(buffer,valread);
}
I'm trying to implement bluetooth piconet using C programming language. I have read some papers and also gone through some examples. But i didn't get proper output. I designed server and client using following example, please check this link. Please check out the code i'm working on:
Can anyone please suggest a proper method to implement it. Thank you.
slave.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <unistd.h>
void send_message_function(char[]);
void receive_ack();
int main()
{
int i;
pthread_t thread1, thread2;
char dest1[18] = "00:1B:10:00:2A:EC";
send_message_function(dest1);
}
void send_message_function(char ptr[18])
{
//printf("MAC::%s",ptr);
struct sockaddr_l2 addr = { 0 };
int s, stat, status, i;
char dest[18], buf[1024];
int bytes_read;
strncpy(dest, ptr, 18);
// allocate a socket
s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
// set the connection parameters (who to connect to)
addr.l2_family = AF_BLUETOOTH;
addr.l2_psm = htobs(0x1001);
str2ba(dest, &addr.l2_bdaddr);
status = connect(s, (struct sockaddr *) &addr, sizeof(addr));
if (status == 0) {
stat = write(s, "hello!", 6);
bytes_read = read(s, buf, sizeof(buf));
if (bytes_read > 0) {
printf("received %s\n", buf);
bzero(buf, 16);
}
}
if (status < 0)
perror("uh oh");
close(s);
}
master.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
void send_ack(char[]);
int main(int argc, char **argv) {
struct sockaddr_l2 loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read,status;
socklen_t opt = sizeof(rem_addr);
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
// bind socket to port 0x1001 of the first available
// bluetooth adapter
loc_addr.l2_family = AF_BLUETOOTH;
loc_addr.l2_bdaddr = *BDADDR_ANY;
loc_addr.l2_psm = htobs(0x1001);
bind(s, (struct sockaddr *) &loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
while(1){
client = accept(s, (struct sockaddr *) &rem_addr, &opt);
memset(buf, 0, sizeof(buf));
// accept one connection
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if (bytes_read > 0) {
printf("received [%s]\n", buf);
status = write(client, "acknowledgement!", 16);
}
//ba2str(&rem_addr.l2_bdaddr, buf);
//send_ack(buf);
}
close(client);
close(s);
}
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.