LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-13-2009, 08:59 AM   #16
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335

The server you use exhibits strange behaviour by only allowing one message to be sent per connection.

Anyhow, concerning the shutdown problems, I've never used shutdown() for any purpose; I believe the close() should suffice.

Btw, you can determine if indeed the server has "kicked" your client off by performing another recv(). If the return value is zero (0), then it's a sure bet that you have been disconnected.

P.S. Please format any code you post using the PHP or CODE tags. These tags need to be specified within square brackets [].

Last edited by dwhitney67; 02-13-2009 at 09:01 AM.
 
Old 02-13-2009, 09:03 AM   #17
wje_lq
Member
 
Registered: Sep 2007
Location: Mariposa
Distribution: FreeBSD,Debian wheezy
Posts: 811

Rep: Reputation: 179Reputation: 179
Quote:
Initializing the buffer to all nulls, as I have shown in my example, was not a big effort. In fact, it is wise to always initialize variables (when they are declared).
If I'm going to initialize a buffer before reading into it or filling it with data for writing, I'll initialize it to something crazy like 0x5A in each byte, and I'll do so before each read() (or before filling it for a write()). That gives me a better (but not 100% rock-solid) indication at debugging time of how much of the buffer I've used.

Filling the buffer with NUL bytes can sometime mask other bugs. I could, for example, have code that plants a NUL byte at the end of what I've just read, and I could be planting that NUL byte in an entirely wrong address (thus yielding erratic, hard-to-reproduce trashing of other data), and I'd never know that if I've initialized the buffer with NUL, but I would if I had used 0x5A.

But I sense that this is a religious issue.
 
Old 02-13-2009, 09:19 AM   #18
Jane2008
Member
 
Registered: Oct 2008
Posts: 36

Original Poster
Rep: Reputation: 15
Thanks. But the close() doesn't work. I tried shutdown() and also failed.

Quote:
Originally Posted by dwhitney67 View Post
The server you use exhibits strange behaviour by only allowing one message to be sent per connection.

Anyhow, concerning the shutdown problems, I've never used shutdown() for any purpose; I believe the close() should suffice.

Btw, you can determine if indeed the server has "kicked" your client off by performing another recv(). If the return value is zero (0), then it's a sure bet that you have been disconnected.

P.S. Please format any code you post using the PHP or CODE tags. These tags need to be specified within square brackets [].
 
Old 02-13-2009, 10:00 AM   #19
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
It's strange that the close() did not work; it works for me.

Anyhow, I took your code and rewrote/refactored it to be hopefully a little more readable. Here it is:
PHP Code:
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>


int connectToServer(const charipAddr, const unsigned short port)
{
  
int sd socket(PF_INETSOCK_STREAM0);

  if (
sd 0)
  {
    
/* Setup info about the remote host*/
    
struct sockaddr_in socketaddr;

    
memset(&socketaddr0sizeof(socketaddr));

    
socketaddr.sin_family      AF_INET;
    
socketaddr.sin_port        htons(port);
    
socketaddr.sin_addr.s_addr inet_addr(ipAddr);

    
/* Connect to the host*/
    
if (connect(sd, (struct sockaddr*) &socketaddrsizeof(socketaddr)) != 0)
    {
      
close(sd);
      
sd = -1;
    }
  }

  return 
sd;
}


void disconnectFromServer(int sd)
{
  
close(sd);
}


charsendCommand(int sd, const charcommand)
{
  
charresponse 0;

  if (
send(sdcommandstrlen(command), 0) > 0)
  {
    
char tmp[1024] = {0};

    
int rstat recv(sdtmpsizeof(tmp) - 10);

    if (
rstat 0)
    {
      
response calloc(1strlen(tmp) + 1);
      
memcpy(responsetmpstrlen(tmp));
    }
  }

  return 
response;
}


void displayMenu()
{
  
printf("Please choose the operation:\n\n");
  
printf("\t1. Read voltage configuration\n");
  
printf("\t2. Read temperature & fan configuration\n");
  
printf("\t3. Write voltage configuration\n");
  
printf("\t4. Write temperature & fan configuration\n");
  
printf("\t5. Read voltage data\n");
  
printf("\t6. Read temperature data\n");
  
printf("\t7. Read fan revolution data\n");
  
printf("\t8. Read switch status\n");
  
printf("\t9. Read system monitor status\n");
  
printf("\t0. Exit\n");
}


int main(int argcchar **argv)
{
  const 
char*        serverAddr "127.0.0.1";
  const 
unsigned int serverPort 9100;
  const 
char*        commands[] = {"\0\n""$U\n""$T\n""%U\n""%T\n""#U\n""#T\n""#F\n","#D\n""#S\n"};
  
unsigned int       choice     0;

  do
  {
    
displayMenu();

    
scanf("%u", &choice);

    if (
choice || choice 9)
      continue;

    
// attempt to connect to the server
    
int sd connectToServer(serverAddrserverPort);

    if (
sd 0)
    {
      
// send the appropriate command
      
charresp sendCommand(sdcommands[choice]);

      
// disconnect from the server
      
disconnectFromServer(sd);

      
// display response (if any)
      
if (resp)
      {
        
printf("resp = %s\n"resp);
        
free(resp);
      }
    }
    else
    {
      
printf("Error:  Can't connect!\n");
    }
  } while (
choice != 0);

 
Old 02-13-2009, 11:05 AM   #20
Jane2008
Member
 
Registered: Oct 2008
Posts: 36

Original Poster
Rep: Reputation: 15
dwhitney67, thank you so much. The code looks much better. The problem is that the close() still didn't work for me, neither shutdown(). I should ask the manufacturer about it. Thanks.
 
Old 02-13-2009, 11:32 PM   #21
j-osh
Member
 
Registered: Nov 2008
Location: Madison, WI
Posts: 34

Rep: Reputation: 16
I am pretty sure you don't need the shutdown command (you could read the man pages to find out what they do).

When you will be using the socket multiple times like in this case it would be better to move the socket setup (socket() connect() etc.) to the main function and then pass the sock descriptor(sd) to you function(io_operation). Then right before you exit out of the main function close the socket. Since you are continually calling your helper function and re-setting up the socket it would be better to move the code to the main function and just leave the socket open the entire time.

This will also save you coding on the server side...cause if you continually open new socket/connections to the server the server will continually have to accept these new connection. If you only open and connect a single socket that you use throughout the program your server will just have to accept this single connection.

Hope this helps
 
Old 02-13-2009, 11:39 PM   #22
j-osh
Member
 
Registered: Nov 2008
Location: Madison, WI
Posts: 34

Rep: Reputation: 16
Also why to you say that close and shutdown are not working for you? Are they returning errors? Or are you not able to reopen a connection the second time? If the later it might be because the system doesn't release ports right away even after they are no longer being used. So you could either just open one socket and use that the entire time or there is a socket option (setsockopt) the you can set right after calling the socket() function to allow reuse of the port bindings but I don't remember the option off hand.
 
Old 02-14-2009, 05:04 AM   #23
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by j-osh View Post
Also why to you say that close and shutdown are not working for you? Are they returning errors? Or are you not able to reopen a connection the second time? If the later it might be because the system doesn't release ports right away even after they are no longer being used. So you could either just open one socket and use that the entire time or there is a socket option (setsockopt) the you can set right after calling the socket() function to allow reuse of the port bindings but I don't remember the option off hand.
What you are writing about above applies to the server side; and from what I understand, the OP is using a COTS server application, for which she does not have the privilege to modify.

The option you are referring to is SO_REUSEADDR that is passed to setsockopt().

Anyhow, since we don't know anything about the server that the OP is using, all I can assume from what the OP describes, is that the issue lies there.

I've taken her original code, and the refactored code I posted earlier that was based on her work, and in each case, both behave well with a server application that I developed that performs the basic operations of accepting connections, receiving client messages, and then sending back a response containing the client message. When the client disconnects, the server is notified of such, and handles it appropriately.

Last edited by dwhitney67; 02-14-2009 at 05:06 AM.
 
Old 02-14-2009, 02:14 PM   #24
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by Jane2008 View Post
First choose the option, then connect, send, recv, close finally. But the close() and shutdown() doesn't work.
shutdown after close probably does nothing since it's supposed to close the descriptor in addition to severing the connection; I'm sure close invalidates the descriptor for the shutdown call.
Quote:
Originally Posted by dwhitney67 View Post
Anyhow, concerning the shutdown problems, I've never used shutdown() for any purpose; I believe the close() should suffice.
I encountered shutdown because of this sort of problem, plus problems rebinding to the same port in cases where both ends haven't called shutdown on a connection associated with the port. close only closes the descriptor, then it's up to the kernel to get around to destroying the connection. You might not have encountered situations where this was a problem, but I have, which is why I use it.
ta0kira
 
Old 02-14-2009, 02:31 PM   #25
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
The binding of a port is done by the server, not the client. I suspect that the vendor that Jane2008 mentioned, is not divulging the proper protocol for the server application, or they wrote a piss-poor application.
 
Old 02-14-2009, 11:10 PM   #26
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
The binding of a port is done by the server, not the client.
Yes, I know that. What I'm saying is that, despite a server closing a socket descriptor bound to a port and the process exiting, sometimes the port won't be available if a client still hasn't terminated the connection (even though the server no longer exists,) which can sometimes happen if only close is used (but more commonly with a hung process.) This is something I've seen enough that the only reasonable cause is a socket left open. Whether or not this is the cause of OP's problem isn't the point; properly shutting down the connection eliminates it as a possibility.
ta0kira
 
Old 03-12-2009, 08:29 AM   #27
Jane2008
Member
 
Registered: Oct 2008
Posts: 36

Original Poster
Rep: Reputation: 15
Thanks for all your help.
The module broken several days ago and i just got a new one yesterday.
I tried to use socket, connect, send, and recv in a loop but it fails.
It seems that the socket only works for the first time. After that, I have to ctrl+c to terminate the program and reset the module.
Also I tried to use socket, after that a loop contains connect, send, and recv. This time the connect only works for the first time. After that, a error occured 'transport endpoint is already connected'.
Any suggestion would be appreciated.
Thanks.
 
Old 03-12-2009, 08:34 AM   #28
Jane2008
Member
 
Registered: Oct 2008
Posts: 36

Original Poster
Rep: Reputation: 15
I also tried the setsockopt(). It doesn't work.
 
Old 03-12-2009, 09:31 AM   #29
Jane2008
Member
 
Registered: Oct 2008
Posts: 36

Original Poster
Rep: Reputation: 15
I also tried socket, connect, then a loop containing send, recv.
The send works well while recv fails after the first time.
The return value of recv() is 0.
At the second time the error is:
recv: success (but still failed)
After that, the error is:
recv : Illegal seek

I think this method doesn't work because the module only support once message send per connection.

Last edited by Jane2008; 03-12-2009 at 11:09 AM.
 
Old 03-12-2009, 05:02 PM   #30
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Jane2008

It seems that the server is still the issue, not your client application. Why don't write your own server so that you can test your client?

The following should help get you going:
Code:
...

int main(int argc, char** argv)
{
  /* use port 9000, unless another port number is given on the cmd line */
  const unsigned short port = (argc > 1 ? atoi(argv[1]) : 9000);

  /* create the socket */
  int sd = socket(AF_INET, SOCK_STREAM, 0);
  assert(sd > 0);

  /* Setup info about the host/port */
  struct sockaddr_in socketaddr;

  memset(&socketaddr, 0, sizeof(socketaddr));

  socketaddr.sin_family      = AF_INET;
  socketaddr.sin_port        = htons(port);
  socketaddr.sin_addr.s_addr = htonl(INADDR_ANY);

  /* bind to the port */
  int rtn = bind(sd, (struct sockaddr*) &socketaddr, sizeof(socketaddr));
  assert(rtn == 0);

  /* listen on the socket */
  rtn = listen(sd, 5);
  assert(rtn == 0);

  for (;;)
  {
    /* wait for a client connection */
    int c_sd = accept(sd, 0, 0);

    for (;;)
    {
      char buf[256]  = {0};
      int  bytesRecv = recv(c_sd, buf, sizeof(buf), 0);

      if (bytesRecv <= 0)  /* error or client disconnected */
      {
        close(c_sd);
        break;
      }

      printf("Received %d byte(s): %s\n", bytesRecv, buf);

      /* add add't code if you need to send a reply back to the client */
    }
  }
}
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
high recv-q and send-q and collision rate sarah_haff Linux - Networking 2 08-19-2008 06:49 AM
Simultaneous Socket Send/Recv in Perl? juanbobo Programming 10 07-28-2008 03:30 AM
MPI Send and Recv mkrems Programming 1 05-25-2008 12:05 PM
recv() and send() in socket lrios Programming 5 04-23-2008 11:32 AM
Infomration regarding the send() and recv() function karimasif Linux - Networking 1 01-13-2008 10:49 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:52 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration