I wrote some code on VxWorks to download a file from a TFTP server using tftpLib but the get gives me a timeout:
ERR [TFTP] tftpSend:479: Transfer Timed Out.
ERR [TFTP] tftpGet:1077: File transfer error.
Error has occurred: 4915207
which isn't right as the host is reachable:
ping("3.94.213.53",3)
Pinging 3.94.213.53 (3.94.213.53) with 64 bytes of data:
Reply from 3.94.213.53 bytes=64 ttl=63 seq=0 time<1ms
Reply from 3.94.213.53 bytes=64 ttl=63 seq=1 time<1ms
Reply from 3.94.213.53 bytes=64 ttl=63 seq=2 time<1ms
and when I do this from the Linux shell, it works just as expected:
tftp -r "artifacts/ngfm.bin" -g 3.94.213.53
What might be the problem here?
The get section of my code looks like:
pFile = fopen("flash:/ngfm.bin","wb");
if (pFile != NULL) {
/* Get file from TFTP server and write it to the file descriptor */
if (OK == (status = tftpGet (pTftpDesc, pFilename, pFile, TFTP_CLIENT))) {
printf("tftpGet() successful\n");
} else {
printf("Error has occurred: %d\n", errno); // errno is where the error is stored
}
} else {
printf("Bad file pointer pFile");
}
edit:
The code I have above the get portion is:
/*Initiate TFTP session*/
if ((pTftpDesc = tftpInit ()) == NULL)
printf("Error on tftpInit()\n");
/*connect to TFTP host and set transfer mode*/
if ((tftpPeerSet (pTftpDesc, pHost, port) == ERROR) ||
(tftpModeSet (pTftpDesc, pMode) == ERROR)) {
(void) tftpQuit (pTftpDesc);
printf("Error on tftpPeerSet()\n");
return ERROR;
}
I believe your problem is caused by lack of calling of tftpModeSet - http://www.vxdev.com/docs/vx55man/vxworks/ref/tftpLib.html#tftpModeSet
So add:
tftpModeSet(pTftpDesc, "binary");
This will prevent your binary file from causing the stream to die off on the first \n
Okay, turns out that TFTP is a no go in my situation.
I hooked up Wireshark and saw that my client is getting through to the server just fine on port 69. I previously have also made sure that I have port forwarding on port 69 setup in my iptable rules properly. Now I just read this on Wikipedia:
Data transfer is initiated on port 69, but the data transfer ports are
chosen independently by the sender and receiver during initialization
of the connection. The ports are chosen at random according to the
parameters of the networking stack, typically from the range of
ephemeral ports
i.e. TFTP won't work for me because I need NAT and it has to be secure. I'll need to go with a protocol that's connection orriented, ftp e.g.
I found that the standar VxWorks library also contains ftpLib.h (http://www.vxdev.com/docs/vx55man/vxworks/ref/ftpLib.html#ftpLs) that will hopefully resolve my NAT issues as FTP works with connection based TCP.
Related
I am new to network programming, and I have some confusion with select function.
For a server program, we need to first create a fd to socket endpoint (server's ip and port without client's ip and port) with socket, bind and listen, then if there is a TCP connection to this socket endpoint, then accept returns the fd to the socket (server's ip, port and client's ip, port). Then we use recv on this socket's fd, and if there is no data to receive, the recv will block (for blocking socket).
I learned that select is used to handle non-blocking multiple connections. But which connection level does it handles? Does it handles multiple socket endpoints, or handles multiple sockets of one single socket endpoint?
For a normal server program, I think the socket endpoint is always single, and there are maybe hundreds of sockets connected to this endpoint. So I think handling multiple socket endpoints may be less useful to handling multiple sockets. But when talking about IO multiplexing, I find that many articles seems talking about handling multiple socket endpoints. While for handling multiple sockets to a single socket, I can't find a way to get all sockets, and put them to select's set of fds, since accept only accepts one sockets a time.
"Does it handles multiple socket endpoints or handles multiple sockets of one single socket endpoint?" -- There is no such thing as multiple sockets of a single socket endpoint. Every socket is an endpoint to the network communication. It just happens that the piece of code which deals with that socket might be different from the others. Consider the following socket descriptors:
int sock_acpt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
listen(sock_acpt, 5);
int sock_cli = accept(sock_apt, ....);
Both the socket descriptors sock_acpt and sock_cli are the endpoints of different communications. After setting sock_acpt in passive mode by calling listen(), the socket just listens for TCP connection, and the server's TCP stack will manage any data that appears on that socket (most probably TCP Handshakes). While sock_cli is the end of an already established connection, and in general, the data on that socket is managed by the user-level application.
Now coming to select(), it is an IO Multiplexer, not a Network IO multiplexer. So any descriptor which can be viewed as an IO endpoint can be used with the select(). Referring to our socket descriptors sock_acpt and sock_cli, both are IO endpoints of different communications, so you can use both of them with select(). You generally do something like below
for ( ; ; ) {
fd_set rd_set;
FD_ZERO(&rd_set);
FD_SET(sock_acpt, &rd_set);
FD_SET(sock_cli, &rd_set);
if (select(sock_acpt > sock_cli ? sock_acpt + 1 : sock_cli + 1, \
&rd_set, NULL, NULL, NULL) <= 0) {
continue;
}
if (FD_ISSET(sock_acpt, &rd_set)) {
// Accept new connection
// accept(sock_acpt, ...);
}
if (FD_ISSET(sock_cli, &rd_set)) {
// Read from the socket
// read(sock_cli, ...);
}
}
But using select() is not limited to sockets, you can use with the file IO (fileno(stdin)), with the signal IO (signalfd()) and any other which can be viewed as IO endpoint.
I'm working at application that works with Minecraft PE servers. I am currently at the position of creating the handshake with the server. Looking at this page http://wiki.vg/Protocol I understand that the status ping works as follows:
C->S : Handshake State=1
C->S : Request
S->C : Response
C->S : Ping
S->C : Pong
C is client and S is server. But I don't understand what bytes/data/hex I need to send. I use https://github.com/robbiehanson/CocoaAsyncSocket to connect and here is the code:
error = nil;
BOOL successs = [self.clientSocket connectToHost:self.serverData[#"host"] onPort:[self.serverData[#"port"] intValue] error:&error];
if (successs)
{
[self.clientSocket writeData:data withTimeout:-1 tag:1];
}
I'm experimenting with LuaSocket for a project I'm working on. I've chosen UDP as my protocol.
Looking for docs and tutorials online, I've attempted to create a client-server pair for testing and learning.
According to what I've read, the following code should work. However, only the server seems to be working properly. The client sends a message, but it will not receive the reply from the server.
Thank you for any help anyone can provide.
Server:
-- Server
#!/usr/bin/env lua5.1
local socket = require("socket")
udp = socket.udp()
udp:setsockname("*", 53474)
udp:settimeout(0)
while true do
data, ip, port = udp:receivefrom()
if data then
print("Received: ", data, ip, port)
udp:sendto(data, ip, port)
end
socket.sleep(0.01)
end
Client:
-- Client
#!/usr/bin/env lua5.1
local socket = require("socket")
udp = socket.udp()
udp:setpeername("127.0.0.1", 53474)
udp:settimeout(0)
udp:send("Data!")
data = udp:receive()
if data then
print("Received: ", data)
end
The timeout value you set is 0, which causes the client timeout every time.
To fix it, give it a positive timeout value:
udp:settimeout(1)
Or set it to nil or a negative value, so it blocks indefinitely:
udp:settimeout()
or
udp:settimeout(-1)
I am making a simple UDP P2P Chat Program with a well known server.
The client's send and recieve data from server and clients through a single IdUDPServer.
The clients as of now can login and logout i.e. they can send data to the server.
Whenever the server sends any data it gets dropped at the NIC side of the node as the embedded ip header checksum is 0x00 as notified by wireshark.
IdUDPServer Settings (Client/Server)
Active : True
Bindings :
Broadcast : False
BufferSize : 8192
DefaultPort : 10000
IPVersion : Id_IPv4
ThreadedEvent : False
Command Used
only one command is used within
UDPServer.SendBuffer ( ED_Host.Text, StrToInt ( ED_Port.Text ), Buffer );
A similar configuration is working perfectly in another program of mine.
Most NICs will perform checksum validation and generation these days instead of the os network stack. This is to improve performance and is known as checksum offloading. As such wiresshark will report the fact the checksum is missing as an error but it can usually be ignored or the error turned off in the wire shark settings.
Some NIC drivers allow you to turn off checksum offloading. Try this and retest the code
I came across the kernel driver code implementing some sort of IGMP snooping backend and as part of its functionalilty it creates a new socket address family, AF_IGMPSNOOP, but actually implements just a few operations for this type of socket:
static struct proto_ops igmp_snoop_ops = {
family: AF_IGMP_SNOOP,
release: _igmp_snoop_sock_release,
bind: sock_no_bind,
connect: sock_no_connect,
socketpair: sock_no_socketpair,
accept: sock_no_accept,
getname: sock_no_getname,
poll: datagram_poll,
ioctl: sock_no_ioctl,
listen: sock_no_listen,
shutdown: sock_no_shutdown,
setsockopt: _igmp_snoop_setsockopt,
getsockopt: sock_no_getsockopt,
sendmsg: _igmp_snoop_sock_sendmsg,
recvmsg: _igmp_snoop_sock_recvmsg,
mmap: sock_no_mmap,
sendpage: sock_no_sendpage,
}
However from a user space perspective a socket is created as:
fd = socket (AF_IGMPSNOOP, SOCK_RAW, IPPROTO_IGMP)
I'm wondering what is the rationale for adding a new family, while in fact a raw socket is being used to access the stack for IGMP packets? Would not it be the same to just create AF_INET raw socket and do the things?
Looking forward to hearing form you !
Thanks.
Mark