iphone tcp connection - iphone

I want to establish tcp connection between iphone and PC. On PC QTspServer is running and working (was tested with other client application).
Here is the connection method i'm using on iphone:
- (IBAction)connectToServer:(id)sender {
CFReadStreamRef read = NULL;
CFWriteStreamRef write = NULL;
NSString *host = #"192.168.1.169";
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, 1000, &read, &write);
CFWriteStreamOpen(write);
int k = 0;
}
The server on PC is not reacting. Any help is appropriate
By the way: Server is nothing more then a QTcpServer with replemented incomingConnection method. Here is the main function on server side:
int main(int argc, char **argv)
{
QApplication app(argc, argv);
AbstractServer server;
server.listen(QHostAddress::Any, 1000);
QLabel label("Hello server");
label.setFixedSize(400, 400);
label.show();
return app.exec();
}

The connection is established after something was sent to the server

Check that write isn't NULL after the call to CFStreamCreatePairWithSocketToHost. If it is, the socket connection is failing.
-(IBAction)connectToServer:(id)sender {
CFWriteStreamRef write = NULL;
NSString *host = #"192.168.1.169";
int port = 1000;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, port, NULL, &write);
if (!write) {
// connection failed.
NSLog(#"Connection to %#:%d failed.",host,port);
} else {
CFWriteStreamOpen(write);
// keep a reference to the output stream for later use.
self.output = (NSOutputStream*)write;
// the function that made the output stream has "Create" in its name, so
// this method owns the write stream & should release it.
CFRelease(write);
}
}
Note that I store the output stream in a property of self. In your sample code, the stream isn't saved anywhere. You don't release it, so it still exists when the method exits, but there's no way of accessing it. If the sample -connectToServer: is representative, that error will prevent your object from sending anything to the server.

Related

Opening a UDP connection in Veins toward external server

I'm using Veins 4.4 and I need to store some results in an outer server, so I would like to open a UDP connection toward it.
I've read several posts about using a TCP connection for the mobility in Veins,and I understood I should resort to the Inet module to open a connection.
Although I don't need it for the mobility, but to send data to an external server.
Is there any suggestion?
I was trying to use the method processCommandFromApp method from inet/src/transport/UDP.cc class:
void UDP::processCommandFromApp(cMessage *msg)
{
switch (msg->getKind())
{
case UDP_C_BIND: {
UDPBindCommand *ctrl = check_and_cast<UDPBindCommand*>(msg->getControlInfo());
bind(ctrl->getSockId(), msg->getArrivalGate()->getIndex(), ctrl->getLocalAddr(), ctrl->getLocalPort());
break;
}
case UDP_C_CONNECT: {
UDPConnectCommand *ctrl = check_and_cast<UDPConnectCommand*>(msg->getControlInfo());
connect(ctrl->getSockId(), msg->getArrivalGate()->getIndex(), ctrl->getRemoteAddr(), ctrl->getRemotePort());
break;
}
case UDP_C_CLOSE: {
UDPCloseCommand *ctrl = check_and_cast<UDPCloseCommand*>(msg->getControlInfo());
close(ctrl->getSockId());
break;
}
case UDP_C_SETOPTION: {
UDPSetOptionCommand *ctrl = check_and_cast<UDPSetOptionCommand *>(msg->getControlInfo());
SockDesc *sd = getOrCreateSocket(ctrl->getSockId(), msg->getArrivalGate()->getIndex());
if (dynamic_cast<UDPSetTimeToLiveCommand*>(ctrl))
setTimeToLive(sd, ((UDPSetTimeToLiveCommand*)ctrl)->getTtl());
else if (dynamic_cast<UDPSetTypeOfServiceCommand*>(ctrl))
setTypeOfService(sd, ((UDPSetTypeOfServiceCommand*)ctrl)->getTos());
else if (dynamic_cast<UDPSetBroadcastCommand*>(ctrl))
setBroadcast(sd, ((UDPSetBroadcastCommand*)ctrl)->getBroadcast());
else if (dynamic_cast<UDPSetMulticastInterfaceCommand*>(ctrl))
setMulticastOutputInterface(sd, ((UDPSetMulticastInterfaceCommand*)ctrl)->getInterfaceId());
else if (dynamic_cast<UDPSetMulticastLoopCommand*>(ctrl))
setMulticastLoop(sd, ((UDPSetMulticastLoopCommand*)ctrl)->getLoop());
else if (dynamic_cast<UDPSetReuseAddressCommand*>(ctrl))
setReuseAddress(sd, ((UDPSetReuseAddressCommand*)ctrl)->getReuseAddress());
else if (dynamic_cast<UDPJoinMulticastGroupsCommand*>(ctrl))
{
UDPJoinMulticastGroupsCommand *cmd = (UDPJoinMulticastGroupsCommand*)ctrl;
std::vector<IPvXAddress> addresses;
std::vector<int> interfaceIds;
for (int i = 0; i < (int)cmd->getMulticastAddrArraySize(); i++)
addresses.push_back(cmd->getMulticastAddr(i));
for (int i = 0; i < (int)cmd->getInterfaceIdArraySize(); i++)
interfaceIds.push_back(cmd->getInterfaceId(i));
joinMulticastGroups(sd, addresses, interfaceIds);
}
else if (dynamic_cast<UDPLeaveMulticastGroupsCommand*>(ctrl))
{
UDPLeaveMulticastGroupsCommand *cmd = (UDPLeaveMulticastGroupsCommand*)ctrl;
std::vector<IPvXAddress> addresses;
for (int i = 0; i < (int)cmd->getMulticastAddrArraySize(); i++)
addresses.push_back(cmd->getMulticastAddr(i));
leaveMulticastGroups(sd, addresses);
}
else
throw cRuntimeError("Unknown subclass of UDPSetOptionCommand received from app: %s", ctrl->getClassName());
break;
}
default: {
throw cRuntimeError("Unknown command code (message kind) %d received from app", msg->getKind());
}
}
delete msg; // also deletes control info in it
}
I included the inet path as follows:
#include <inet/src/transport/udp/UDP.h>
and I call it as follows, by passing as input UDP_C_CONNECT message.:
cMessage *UDP_C_CONNECT;
void Inet::UDP::processCommandFromApp(UDP_C_CONNECT);
But when I run the simulation, it crashes, returning this error:
Errors occurred during the build.
Errors running builder 'OMNeT++ Makefile Builder' on project 'veins'.
java.lang.NullPointerException
1) Is there the correct way to set up the required connection?
2) Why I'm getting this error as soon as I include the inet path?
UPDATE
I also tried another way to establish the connection:
std::string host;
host = "16777343";
int port = 5144;
Veins::TraCIConnection* connection;
connection = TraCIConnection::connect(host.c_str(), port);
but as soon as it load the plugin, then it's like it is waiting for something at time 0.0 without starting the generation of the nodes.
Thanks for helping
Simulations using OMNeT++ are C++ programs, so you can use the full range of libraries and system calls available to any C++ program. If you want to open a UDP connection to some other computer on your network, just create a UDP socket as you would in any C++ program, then send the data whenever needed.
Maybe the easiest way to go about writing this is to
start with a plain C++ program that has nothing to do with OMNeT++
move the part of the program that has to run before everything else into the initialize method of a module in your simulation, the rest to a handleMessage method.

Not able to receive File name in server sent by client

I am trying to write a simple socket program which reads a file name in client and sends it to the server. The contents of file are sent to the Client back if present. The client and server are able to successfully able to connect but when I read a file name I don't get any output(program doesn't terminates). Please tell me what is going wrong.
server.c
int main()
{
int create_socket,new_socket,fd,addlen,n;
int bufsize=1024;
char *buffer=malloc(bufsize);
char fname[255];
struct sockaddr_in address;
//printf("program");
if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0)
printf("socket created");
address.sin_family=AF_INET;
address.sin_port=htons(15000);
address.sin_addr.s_addr=INADDR_ANY;
if(bind(create_socket,(struct sockaddr*)&address,sizeof(address))==0)
printf("socket binded");
while(1)
{
printf("Inside while loop");
listen(create_socket,3);
addlen=sizeof(struct sockaddr_in);
if(new_socket=accept(create_socket,(struct sockaddr*)&address,&addlen)>0)
printf("%d connected",inet_ntoa(address.sin_addr));
else
printf("not connected");
recv(new_socket,fname,255,0);
printf("file name is %s",fname);
if(fd=open(fname,O_RDONLY)<0)
{
strcpy(buffer,"Not such file found");
send(new_socket,buffer,sizeof(buffer),0);
}
else
{
while(n=read(fd,buffer,bufsize)>0)
send(new_socket,buffer,n,0);
}
close(new_socket);
}
close(create_socket);
}
client.c
int main(int argc,char *argv[])
{
int create_socket,n;
int bufsize=1024;
char *buffer=malloc(bufsize);
char fname[255];
struct sockaddr_in address;
if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0)
printf("socket created\n");
address.sin_family=AF_INET;
address.sin_port=htons(15000);
inet_pton(AF_INET,argv[1],&address.sin_addr);
if(connect(create_socket,(struct sockaddr*)&address,sizeof(address))==0)
printf("%s connected\n",argv[1]);
else
printf("not connected\n");
printf("Enter the filename\n");
scanf("%s",fname);
send(create_socket,fname,strlen(fname),0);
printf("get the values");
while(n=recv(create_socket,buffer,bufsize,0)>0)
write(1,buffer,n);
return close(create_socket);
}
With the information provided, two problems with transmitting the file name are apparent:
(1) You do not check the return value of send. You cannot be sure what is sent.
(2) You choose not to send the terminating '\0' over the network. Therefore, the receiver has no way of determining when the complete file name has been received. The receiver also does not check the return value of recv. Additionally, the receiver does not bother to terminate the received filename with a '\0'.

Fail to Bind Socket

I've been writing a server and every time I quit it and re-open it, it seems to fail to bind to the socket. I'm connecting 2 clients and then disconnecting them with close() before I shut down the server, I also then quit the clients before opening the server just in case, however it still seems to fail and I have to restart my computer. Here is my code:
listenSocket = device = app = 0;
struct sockaddr_in server_addr;
char buffer[1024];
listenSocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, '0', sizeof(server_addr));
memset(buffer, '0', sizeof(buffer));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(35565);
//bind the socket
if (bind(listenSocket,(struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
NSLog(#"Error binding to socket");
}
if (listen(listenSocket, 5) == -1) {
NSLog(#"Failed to listen");
}
//launch thread for console
[NSThread detachNewThreadSelector:#selector(console) toTarget:self withObject:nil];
NSLog(#"Starting server");
//socket open, ask for clients
while (true) {
int client = -1;
if (!device || !app)
client = accept(listenSocket, (struct sockaddr*)NULL, NULL);
//handshake omitted for length
}
And the code to close the server:
close(listenSocket);
close(device);
close(app);
NSLog(#"Clean");
Is there something I'm doing wrong? Any help would be appreciated. Thanks.
EDIT: Here is my error checking code:
NSLog(#"%s",strerror(errno));
int e = bind(listenSocket,(struct sockaddr*)&server_addr, sizeof(server_addr));
NSLog(#"%s",strerror(errno));
You need to set the SO_REUSEADDR option. Otherwise, once you grab the port in a process, there is a significant timeout before the kernel will let you have it again. Much detail to be found in an existing question; I've voted to close as a duplicate.
I had a similar problem which was caused by another process holding on to the ports. Killing that process solved the problem.

ios - Determine if a certain address with a certain port is reachable

I want to know if my server is online via my ios application. Here's what I'm doing:
Boolean result;
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFDataRef)(serverIPAddress)); //serverIPAdress = "10.10.10.100:5010"
if(hostRef) {
result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL); // pass an error instead of NULL here to find out why it failed
}
if (!result) { //This means that the host was unreachable
return ;
}
My server is online and I can access it later on in the code(meaning that my connection to the server works perfectly fine). However, I want to be able to detect if my server, on a certain port, is reachable.
Also, if I remove the ":5010" from the ip address, it detects that my server is online (it doesn't go in the "!result" condition) and detects that my server is offline if I put "10.10.10.253" which corresponds to no ip address on my network.
How can I manage to determine if my server is online or not ?
I've looked at this question : Reachability with Address - Server AND Port - iOS 5 but it doesn't work since it always return that it is reachable no matter what ip address I enter
Thanks in advance
One approach could be to open a socket connection to a specific port to see if you get any response back. If not, then the destination is unreachable. For example
#include <arpa/inet.h> //for PF_INET, SOCK_STREAM, IPPROTO_TCP etc
CFRunLoopSourceRef gSocketSource;
void ConnectCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
UInt8 buffer[1024];
bzero(buffer, sizeof(buffer));
CFSocketNativeHandle sock = CFSocketGetNative(socket); // The native socket, used recv()
//check here for correct connect output from server
recv(sock, buffer, sizeof(buffer), 0);
printf("Output: %s\n", buffer);
if (gSocketSource)
{
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
if (CFRunLoopContainsSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode))
{
CFRunLoopRemoveSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode);
}
CFRelease(gSocketSource);
}
if (socket) //close socket
{
if (CFSocketIsValid(socket))
{
CFSocketInvalidate(socket);
}
CFRelease(socket);
}
}
void ConnectSocket()
{
//socket
CFSocketContext context = {0, NULL, NULL, NULL, NULL};
CFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack , (CFSocketCallBack)ConnectCallBack, &context);
//address
struct sockaddr_in socketAddress;
memset(&socketAddress, 0, sizeof(socketAddress));
socketAddress.sin_len = sizeof(socketAddress);
socketAddress.sin_family = AF_INET;
socketAddress.sin_port = htons(5010);
socketAddress.sin_addr.s_addr = inet_addr("10.10.10.253");
gSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, theSocket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), gSocketSource, kCFRunLoopDefaultMode);
CFDataRef socketData = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&socketAddress, sizeof(socketAddress));
CFSocketError status = CFSocketConnectToAddress(theSocket, socketData, 30); //30 second timeout
//check status here
CFRelease(socketData);
}
Basically, if the server is unreachable at that port, you will most likely get a kCFSocketTimeout for CFSocketError status. If you are looking to parse a specific response back from the server to determine if the server is ready or not, the ConnectCallBack function will be called upon successful socket connection.
This is just a simple example, make sure not to block the UI by calling socket connections on the main thread such as recv()

How to make a G-WAN servlet close its connection silently without sending any reply

How to have gwan send no reply to some requests, i.e. make a servlet closed silently without building and sending a reply?
It is useful to reduce the out-going bandwidth from the server side.
For collecting data only, there's no need to respond anything to the client.
You can also close the connection from the servlet by doing something like (untested):
#include <sys/socket.h>
char buf[1024];
int s = (int)get_env(argv, CLIENT_SOCKET);
shutdown(s, SHUT_WR);
while(read(s, buf, sizeof(buf)) > 0);
close(s);
return 500;
Then return something like 500 like above so you don't have to build a reply.
You can do that with a gwan connection handler.
I think this is the event that you need to catch on the handler. Since you want the servlet to run then close the connection after.
HDL_BEFORE_WRITE, // after a reply was built, but before it is sent
Here is a sample code for the connection handler. You still need to add your filter. This code will close all requests after the reply was built.
int init(int argc, char *argv[])
{
u32 *states = (u32*)get_env(argv, US_HANDLER_STATES);
*states = (1 << HDL_BEFORE_WRITE)
}
int main(int argc, char *argv[])
{
long state = (long)argv[0];
if(state == HDL_BEFORE_WRITE)
{
return 0; // Close connection
}
return(255); // continue G-WAN's default execution path
}