iphone sdk/mac - Yet another problem with sockets - iphone

My program consists of 2 parts - A server socket (sits on port 3490) running on a different thread, and a client to test the server. Now the server has a pdf file, and I want the client to display it in a UIWebView. To achieve this I used the folllowing:
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://127.0.0.1:3490/"]];
[webView loadRequest:urlRequest];
The problem is that when a server posts its request I get in the console:
unable to open '': No such file or directory
In the server the most important part of the code is:
int fileDesc = open(viewController.filePath, O_RDONLY);
if (fileDesc == -1) {
fprintf(stderr, "unable to open '%s': %s\n", viewController.filePath, strerror(errno));
exit(1);
}
off_t offset = 0;
off_t len = 0;
struct sf_hdtr headers;
headers.headers = NULL;
headers.trailers = NULL;
if (sendfile (fileDesc, new_fd, offset, &len, &headers, 0) == -1){
perror("send");
}
Basically what I'm trying to do is to send the file via the socket to the client. Probably something is wrong here.
The rest of the server is pretty long so I'll just provide the link to it (It's modified - instead of send I use sendFile). http://beej.us/guide/bgnet/output/html/multipage/clientserver.html#simpleserver
Please help
Thanks
Alex
EDIT: Nevermind. I solved the issue. it seems that [viewController.filePath UTF8String] is needed in open(viewController.filePath, O_RDONLY);

Nevermind. I solved the issue. it seems that [viewController.filePath UTF8String] is needed in open(viewController.filePath, O_RDONLY);

Related

C socket server: What's the right way to read all of an unknown length XMLHttpRequest?

I have a simple XMLHttpRequest handler written in C. It reads and processes requests coming from a JavaScript XMLHttpRequest send() running in a browser.
The parent process accepts incoming connections and forks a child process for each incoming connection to read and process the data.
It works perfectly for most requests, but fails in some cases (apparently related to the network infrastructure between the client and the server) if the request is over about 2 kB in length. I'm assuming that the request is being broken into multiple packets somewhere between the browser and my socket server.
I can't change the request format, but I can see the request being sent and verify the content. The data is a 'GET' with an encoded URI that contains a 'type' field. If the type is 'file', the request could be as long as 3 kB, otherwise it's a couple of hundred bytes at most. 'File' requests are rare - the user is providing configuration data to be written to a file on the server. All other requests work fine, and any 'file' requests shorter than about 2 kB work fine.
What's the preferred technique for ensuring that I have all of the data in this situation?
Here's the portion of the parent that accepts the connection and forks the child (non-blocking version):
for (hit = 1;; hit++) {
length = sizeof(cli_addr);
if ((socketfd = accept4(listensd, (struct sockaddr *) &cli_addr, &length, SOCK_NONBLOCK)) < 0){
//if ((socketfd = accept(listensd, (struct sockaddr *) &cli_addr, &length)) < 0){
exit(3);
}
if ((pid = fork()) < 0) {
exit(3);
} else {
if (pid == 0) { /* child */
//(void) close(listensd);
childProcess(socketfd, hit); /* never returns. Close listensd when done*/
} else { /* parent */
(void) close(socketfd);
}
}
}
Here's the portion of the child process that performs the initial recv(). In the case of long 'file' requests, the child's first socket recv() gets about 1700 bytes of payload followed by the browser-supplied connection data.
ret = recv(socketfd, recv_data, BUFSIZE, 0); // read request
if (ret == 0 || ret == -1) { // read failure stop now
sprintf(sbuff, "failed to read request: %d", ret);
logger(&shm, FATAL, sbuff, socketfd);
}
recv_data[ret] = 0;
len = ret;
If the type is 'file', there could be more data. The child process never gets the rest of the data. If the socket is blocking, a second read attempt simply hangs. If the socket is non-blocking (as in the snippet below) all subsequent reads return -1 with error 'Resource temporarily unavailable' until it times out:
// It's a file. Could be broken into multiple blocks. Try second read
sleep(1);
ret = recv(socketfd, &recv_data[len], BUFSIZE, 0); // read request
while (ret != 0){
if (ret > 0){
recv_data[len+ret] = 0;
len += ret;
} else {
sleep(1);
}
ret = recv(socketfd, &recv_data[len], BUFSIZE, 0); // read request
}
I expected that read() would return 0 when the client closes the connection, but that doesn't happen.
A GET request only has a head and no body (well, almost always), so you have everything the client has sent as soon as you have the request head, and you know when you have read the whole request head when you read a blank line i.e. two returns (and no sooner or later).
If the client sends just a part, without the blank line, you are supposed to wait for the rest. I would put a time-out on that and reject the whole request if it takes too long.
BTW there are still browsers out there, and maybe some proxies as well, with a URL length limit of about 2000 characters.

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.

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.

mongoose http server fails to get post data sometimes

when I use mongoose to process some http requests, it fails to get post data sometimes. Has anyone met the some problem? I am not sure whether the mongoose is stable enough. Can anyone give some ideas?
Thanks in advance.
I use the restClient to send the http request.
The mongoose library is downloaded from:http://code.google.com/p/mongoose/
The problem I encountered is
Uploading the file size exceeds 120MB, the will be a memory warning, and then the program crashes.After a preliminary test, to find the code of memory level 2 warnings:
MongooseServer.m
void *handleRequest(enum mg_event event,
struct mg_connection *conn,
const struct mg_request_info *request_info)
{
...
if ((cl = mg_get_header(conn, "Content-Length")) != NULL) {
len = atoi(cl);
if ((buf = malloc(len)) != NULL) {
mg_read(conn, buf, len);
body = [NSData dataWithBytes:buf length:len];
free(buf);
}
}
...
}
Specific problem is where I also did not identify, had determined after further debugging

Image Sending to a server using SocketCommunication

Using J2ME I need to send a JPEG image to a server using Socket Communication. Can anyone send me a sample code for my application?
Take a look at this article from Sun Developer Network. It has some minimalistic examples and should give you some ideas.
...
SocketConnection client = (SocketConnection) Connector.open("socket://" + hostname + ":" + port);
// set application-specific options on the socket. Call setSocketOption to set other options
client.setSocketOption(DELAY, 0);
client.setSocketOption(KEEPALIVE, 0);
InputStream is = client.openInputStream();
OutputStream os = client.openOutputStream();
// send something to server
os.write("some string".getBytes());
// read server response
int c = 0;
while((c = is.read()) != -1) {
// do something with the response
}
// close streams and connection
is.close();
os.close();
client.close();
...