1

So I was writing a c++ class to make unix sockets in c a bit easier. However, every time I run it it fails to connect. The value of the port changes midway through the program. Here is the header file with the class:

#ifndef __Sockets__CHSocket__
#define __Sockets__CHSocket__
class Sock {
    int port;
    char host[16];
    int sock,maxLen;
    int bytes;
    long nHostAddress;
    struct hostent* pHostInfo;
    struct sockaddr_in dest;

public:
    Sock(int dom, int type);
    int connct(const char *host, int port);
    int bnd(const char *addr, int port);
    int lstn(int port);
    int snd(const char *toSend);
    int sndto(const char *msg, const char *dst);
    char* recv(int length);
    int accpt(int s, struct sockaddr *addr, socklen_t *addrlen);
    int clse();
};  
#endif /* defined(__Sockets__CHSocket__) */

Here is CHSocket.cpp (shortened to what is actually run):

// Constructor definition
Sock::Sock(int dom, int type)
{
    bzero(&dest, sizeof(dest));
    if ((sock=socket(dom, type, 0)<0)) {
        cerr << "[!] Failed to create socket!;";
    }
    dest.sin_family=dom;
    memset(&dest, 0, sizeof(dest));
}

// Connect definition
int Sock::connct(const char *host, int port)
{
    char theHost[sizeof(host)];
    strcpy(theHost, host);
    pHostInfo=gethostbyname(theHost);
    memcpy(&nHostAddress,pHostInfo->h_addr,pHostInfo->h_length);

    dest.sin_addr.s_addr=nHostAddress;
    dest.sin_port = htons(port);
    if (connect(sock, (struct sockaddr *)&dest, sizeof(dest)) < 0)
    {
        cerr << "[!] Failed to connect socket!";
        return -1;
    }
    else
    {
        return 0;
    }
    return 0;
}

Here is main.cpp:

int main()
{
    Sock test = Sock(AF_INET, SOCK_STREAM);
    test.connct("127.0.0.1", 3000);
    test.clse();
}

I am using xcode 5 on osx 10.8. When I ran the program it told me that it could not connect. I put in some breakpoints at the very beginning of the connect function and at the line that defines pHostInfo. At the first break point, value of port is 3000, at the second, it is 49. Is this related to the connect issue?

UPDATE:

The program runs now but it gives me the following output:

[!] Failed to connect socket!Program ended with exit code: 0

This is what it does when it fails to connect the socket. I have netcat listening on port 3000 and I successfully connected from another window. Any ideas what the issue might be?

735Tesla
  • 3,162
  • 4
  • 34
  • 57
  • 1
    You're using a [reserved identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). – chris Oct 11 '13 at 23:34
  • 3
    I don't mean to be harsh, but with function names like that I'd use the original API over yours without any hesitation whatsoever. – syam Oct 11 '13 at 23:40
  • @syam that's irrelevant to the question, but still you are correct. it's not 1987 any more, computers have a lot of memory, no need to save it for that purpose anymore. – ipinak Oct 11 '13 at 23:46
  • @ipinak Actually it was about saving keystrokes rather than memory (back in the day it was a real pain to input data on teletypes / perforated cards / whatever), but Ritchie himself later admitted it was a mistake. And we're speaking more like 1970 than 1987. ;) – syam Oct 11 '13 at 23:57

2 Answers2

3
char theHost[sizeof(host)];

gives you an array with space for sizeof(char*). You actually need strlen(host)+1 bytes so are probably over-writing memory inside the subsequent strcpy. Changing this would require either support for VLAs (which isn't present as standard) or unnecessary dynamic allocation.

It'd be easier to just remove theHost, using host in its place.

simonc
  • 41,632
  • 12
  • 85
  • 103
  • 2
    Depending on the compiler, `gcc` and `clang` support VLA as as [extension in C++.](http://stackoverflow.com/a/19136083/1708801) – Shafik Yaghmour Oct 11 '13 at 23:34
  • @chris Thanks, another detail I hadn't realised. Answer now updated. – simonc Oct 11 '13 at 23:37
  • @chris: Not anymore. Never in the form C has them, and `std::dynarray` has been removed/postponed. – GManNickG Oct 11 '13 at 23:37
  • @GManNickG, I know for sure the original plan was to have both, and I know `std::dynarray` was moved to a TS, but I thought VLAs were still in. – chris Oct 12 '13 at 01:39
  • @chris: Ah, I thought C-style VLAs were never considered because they suck. I hope they reconsider... – GManNickG Oct 12 '13 at 01:52
3
char theHost[sizeof(host)];

That line allocates enough bytes to just store the size of host, which is a pointer to char, which will probably be 8. It then overwrites the port number because you don't have enough memory allocated on the stack. You probably want the following:

char *theHost = new char[strlen(host)+1]

and then free that memory afterwards, before your constructor returns:

delete [] theHost;

Alternatively, and easier and better, you can just use the host argument directly in your call to gethostbyname()

edit: (added deallocation, as suggested)

yan
  • 20,644
  • 3
  • 38
  • 48
  • If you're going to recommend dynamic allocation, it'd be worth mentioning the need to later call `delete[]` – simonc Oct 11 '13 at 23:36
  • 3
    @syam smart pointers would solve the memory leak, but I think what really needs to happen is to skip the allocation and just use the argument in place – yan Oct 11 '13 at 23:39