Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Sockets Programming

Status
Not open for further replies.

BrownOut

Banned
or "My First Socket Program"

First of all, I know there is another forum for these kinds of questions, but they seem to be visited by a subset of ETO members, so I want to get as large of an audiance as possible. With that said:

I am developing a system that acquires data at medium-high speed and bridges to a standard 10/100 Ethernet to transfer the data to a host computer. The system has a single Ethernet connection, phy, MAC, etc. Right now, I have the sockets accepting commands from the host for running board diagnostics and executing simlpe commands. The application only accepts 32 Byte cmmands from the host. But, I want to stream the high-speed data and use abitrarily long packtes ( up to the 1500 byte ethernet limit ) So my question is this: Is the correct way to do this to open a different socket on a different port for the high speed data and different program thread for capturing and processing? The seems to be the only way to do it, but as I'm a socket programing neophyte, I'm not sure if I'm missing something????

Thanks

OH, and BTW, the RTOS is UC/OSII, and the IP stack is the Niche stack, if that helps.
 
Last edited:
You said the application only accepts 32 byte commands, but it can transmit more? I wouldn't see any reason to do anything, simply send the larger packets on the same socket, ethernet doesn't 'expect' a certain packet size only possibly the application. If the application can transmit the larger packet and the host doesn't have the same limit as the application then there's nothing that needs to be done at all, just send the data.
 
A little more detail. The 32 byte limit is set by other parameters in the system. Namely, the peripheals (LCD displays, etc) are 32 byte, and so there is no reason to go higher for the user interface. I also need to send data of an arbitrary size to the system for transmission on the 'other media.' In other words, there are two distince streams, the usesr interface and the high speed interface. So I really can't use the same channel. Unless there is a way to redirect the traffic to a different thread. I'm sure there is, but I really don't want the extra overhead of checking, but on the other hand, having a 2nd socket for high speed data might be more overhead.
 
Last edited:
I'm unfamiliar with the stack you're using BrownOut, why would you need to change channels? The byte size of a packet isn't fixed, it's simply a value, before you transmit the high speed data you would change the packet length to your required length, send the byte(s) and then change it back if that's the degree of control you have, something like packet length should be virtually transparent to the software.

What am I missing? Can you provide a quick PDF primer to the Niche stack you've referenced? I simply don't understand why the 'problem' of packet length is coming up, the stack is what is supposed to deal with it not the user. All the application should ever see is data.
 
The Niche stack operates the same as any other stack. The limit of the packet I can send is determined by the application program. It has a facility for a user interface, and it's limited to 32 bytes, just enough for issing commands and receiving status. I don't want to have to deal with large buffers for that interface. The other problem is if I'm reveiving arbitrary data, then it's possible ( likely ) that some packet will look like a command, but in fact overflow the command buffers and crach the application. So, I'm asking what is the best way to handle multiple data streams.

The actual receive buffer is large enough for the longest possible packet. But the command buffers expect 32 bytes maximu.
 
Last edited:
Or to put the question another way; does anyone have any insight concerning the overhead of using a 2nd socket for the other stream vs using the same socket and interrogating the packets to send to different threads. I have a feeling there is probably not much difference, but I'm too green to know.

Or maybe some 3rd option that I haven't thought of. The reason I'm a little concerned obout overhead is because I'm runing this on a low end embedded processor, and I think I'll be pushing the limits of it's processing capability.
 
Last edited:
*bump*

After thinking about about it, and considering how the IP stack would work in a mulit tasking environment, I think it would add negligable overhead to have a different socket for the high speed connection. My theory goes like this: all listening sockets are suspended while waiting for the client to send data. The RTOS starts which ever thread is appropriate for the target socket. Any checking by the OS will be done wether there is one or multiple sockets. Actually, I think I need a listening socket for the server side ( data from host ) and a connect socket for the client side ( data to the host ) I know this is really, really basic, but I'm not an embedded programmer.....yet.

Comments?
 
Last edited:
In case anyone is still readling... I discovered two methods for sending and receiving data over a socket and avioding the "blocking" issue ( that's where, for example, a client has a call to read() which is blocking, and the server has the same call blocking, resulting in the "deadly embrace" ) One solution is to have the socket writes and reads in independent threads. I was able to download source code for a telnet client that uses this method. Can post link if anyone is interested. The second way is to use the system call select(). You can pass an integer that represents all of the socket descriptors you're interested, and the reuturn interger will indicate which sockets need servicing. There are alot of details, so I won't go into all of them, but I do see light at the end of the tunnel now.

You can also use other 'non-blocking' methods and system calls. There are just two solutions. I will implement one of them in my program.
 
Still reading, I think I see your dilemma more clearly now. The stack you're using is pretty thin, I was assuming something of a higher order as far as management goes where most of that stuff is taken care of for you.
 
To be honest, there are numerous ways to accomplish the same thing. I'm looking for the 'cleanest' way, not having to write a bunch of code to figure out what streams I'm receiving. I have access to some socket functions form the stack that helps, but I have looked over how other programs work, and I think I know how I want to preceed now. I'll post what little code I have in a second, and maybe that will clarify things a little.
 
As promised, here is the code so far. Some of the code was purposly left out just to make it more readable and so the reader can get the general idea what I'm trying to do. I'm initializing my system by creating two "listening" sockets, one for high speed data and one for short control messages. Although it may seem like alot of overhead to create two sockets, it will make the coding of processing the data and control simpler and faster. The first lines are to create the two sockets and set them up for listening. Then, the code inside the while() statement calles "select()" and passes in an integer which represents both sockets. This call returns if an attempt is made by a client to connect to either of these sockets. The FD_ISET macro determines if the socket was marked for servicing by the select() function. That avoids the situation where one call to wait for a connection blocks the call for the other connection, ie waiting for a connection on the data socket blocks the control socket, requiring a connection on data to enable connection to control. Once a connection is made, I'll call a two threads that services rx and tx on each connected socket. This isn't the only way to do it, but I think it's the best way, at last as far as my knowledge of socket programming goes.

Code:
void main() {
    int maxfdp;
    fd_set rset;
    int fd_ctl_lstn, fd_data_lstn;
    struct sockaddr_in dat_sock_addr, ctl_sock_addr;
    
    /*set up Data socket*/
    if((fd_data_lstn=socket(AF_INET, SOCK_STREAM, 0)) = -1) {
        //Change to a better error handler
        printf("Error in data socket creation, %d", fd_data_lstn);
        exit(1);
    }
    
    bzero(&dat_sock_addr, sizeof(dat_sock_addr));
    dat_sock_addr.sin_faily = AF_INET;
    dat_sock_addr.s_addr = htonl(INADDR_ANY);
    dat_sock_addr.sin_port = htons(DATPORTNUM); //need definition
    if(bind(fd_data_lstn, (struct sock_addr *)&dat_sock_addr, sizeof(dat_sock_addr)) == -1) {
        //Change to a better error handler
        printf("Error in data socket binding")
        exit(1);
    }
    
    if(listen(fd_data_lstn, LESTENQ) == -1) {
        //change to a better error handler
        printf("Error in data listen conversion\n");
        exit(1);
    
    }
    
    /*Set up the Command socket*/
    if((fd_ctl_lstn=socket(AF_INET, SOCK_STREAM, 0)) = -1) {
        //Change to a better error handler
        printf("Error in control socket creation, %d", fd_ctl_lstn);
        exit(1);
    }
    
    bzero(&ctl_sock_addr, sizeof(dat_sock_addr));
    ctl_sock_addr.sin_faily = AF_INET;
    ctl_sock_addr.s_addr = htonl(INADDR_ANY);
    ctl_sock_addr.sin_port = htons(DATPORTNUM); //need definition
    if(bind(fd_ctl_lstn, (struct sock_addr *)&ctl_sock_addr, sizeof(ctl_sock_addr)) == -1) {
        //Change to a better error handler
        printf("Error in control socket binding")
        exit(1);
    }
    
    if(listen(fd_ctl_lstn, LESTENQ) == -1) {
        //change to a better error handler
        printf("Error in control listen conversion\n");
        exit(1);
    
    }

    while(1) {
        //Build the FD_set array to be passed into the select system call.  This 
        //requires special macros FD_SET and FD_ZERO.

        //Missing code here for readability

        select(maxfdp, &rset, NULL, NULL, NULL); //Wait until one of the socket descriptors in "rset" has data


        if(FD_ISET(fd_data_lstn, &rset)) {
            //call function to accept connection on data stream
        }
        if(FD_ISET(fd_ctl_lstn, $rset)) {
            //call function to accept connection on control stream
        }
    }
}
 
Last edited:
Here is a block diagram of what I'm atttempting to do. Maybe it helps.
 

Attachments

  • software_scheme.JPG
    software_scheme.JPG
    64.2 KB · Views: 177
NiosII "soft" processor in Altera FPGA technology. I'm using Alter'a SOPC builder and the avalon architecture, along with Altera provided Eclipse software build tools. And of course, the Niche stack running on USCOSII. I'll write more later if anyone is still interested. I won't be able to post on here for a few days.
 
That sounds amazing or horrifying I'm not sure! A soft processor core in an FPGA. My, how things have progressed. I started electronics before FPGA's were available. I've used one and it was great but the complexity level has gone through the roof. Thanks for the info. I'll keep watching.
 
UPDATE: The program is working very well. Using coherent threads for rx & tx was devine inspiration :) I have two sockets, one for data and one for command & status. To test them, I opened two seperate telnet sessions and had them talk to each other. Now the utility of having a command socket is more apparent, because I'm going to use it to stream data to the embedded system and read it off of the data socket, for data rate testing and such. Next up is to insert a DMA engine which will be the main conduit for the data collection. Again, I'll use the command socket to stream data to the DMA block, and the data socket to verify correctness.

I dont' know if I can post the code, since this is a paid gig. But if anyone is interested, I can show the methods and some of the code.
 
Last edited:
I would be interested. Thanks for the update. What sort of development tools are you using for the code?
 
Hi moffy. I'm using Eclipse Software Build Tools. I might write it up on my blog, and then I'll post a notification here. I might write it in installments ( it's a paying gig I'm working on )
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top