Пример #1
0
int Sock_connect(Sock_port_t port, char *sname, Sock_error_t perr)
{
  struct sockaddr_in server;
  struct hostent *hp;
  int sock;
  int retval;
 
  if (! (hp = gethostbyname(sname))
      || (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    return Sock_error(perr, errno, h_errno);
       
  memcpy((char *)&server.sin_addr, hp->h_addr_list[0], hp->h_length);
  server.sin_port = htons((short)port);
  server.sin_family = AF_INET;

  do
    retval = connect(sock, (struct sockaddr *) &server, sizeof(server));
  while (retval == -1 && errno == EINTR);
  if (retval == -1) {
    Sock_error(perr, errno, 0);
#ifdef _Windows
    closesocket(sock);
#else
    close(sock);
#endif
    return -1;
  }
  return sock;
}
Пример #2
0
/* open a socket for listening */
int Sock_open(Sock_port_t port, Sock_error_t perr)
{
#ifdef HAVE_SOCKETS
    int sock;
    struct sockaddr_in server;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	return Sock_error(perr, errno, 0);

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons((short)port);

#ifndef Win32
    /* According to Stephens (1998) "Unix Network Programming, Vol 1",
       pp. 194 on UNIX we need to set the SO_REUSEADDR socket option
       if we want to be able to have a server create several
       connections that are open simultaneously.  If this option is
       not set, the call to `bind' will fail when attempting to open
       another server socket on a given port if a connection made to
       that port is still alive. This is not an issue if each socket
       connection is handled and terminated before the next server
       socket is created.  Stephens recommends setting SO_REUSEADDR on
       all servers.  Even with this option set it remains impossible
       to establish two simultaneous servers on the same IPADDR/port
       combination.  Tcl 8.3 uses the bit of code used here in
       tclUnixChan.c, so it should work on most UNIX platforms.

       Unfortunately things are different on Windows.  According to
       Quinn and Shute (1996) "Windows Sockets Network Programming",
       pp. 305, Windows sockets are quite happy to allow two servers
       to use the same IPADDR/port, with unpredictable results, if
       SO_REUSEADDR is set.  So setting this option on Windows is not
       a good idea.  It is unclear whether it is possible on WIndows
       to establish a new server socket while a connection from a
       previous server socket is still active.

       This would be less of an issue, but would not entirely
       disappear as an issue. if the R interface separated the
       `socket'/`bind'/`listen' part of setting up a server socket,
       which is only needed once per server instance, from the
       `accept' part, which is needed for each connection.  LT */
    {
	int val = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
    }
#endif

    if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) ||
	(listen(sock, MAXBACKLOG) < 0))
	return Sock_error(perr, errno, 0);
    return sock;
#else
    error(socket_msg);
    return(-1);
#endif
}
Пример #3
0
int Sock_close(int fd, Sock_error_t perr)
{
#ifdef _Windows
  if (closesocket(fd) != 0)
    return Sock_error(perr, WSAENOTSOCK, 0);
#else
  if (close(fd) < 0)
    return Sock_error(perr, errno, 0);
#endif
  else
    return 0;  
}
Пример #4
0
int Sock_listen(int fd, char *cname, int buflen, Sock_error_t perr)
{
  struct sockaddr_in net_client;
  int len = sizeof(struct sockaddr);
  int retval;
  struct hostent *hostptr;

  do
    retval = accept(fd, (struct sockaddr *)(&net_client), &len);
  while (retval == -1 && errno == EINTR);
  if (retval == -1)
    return Sock_error(perr, errno, 0);

  if (cname != NULL && buflen > 0) {
    size_t nlen;
    char *name;
    struct in_addr *iaddr = &(net_client.sin_addr);
    hostptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
    name = (hostptr == NULL) ? "unknown" :  hostptr->h_name;
    nlen = strlen(name);
    if (buflen < nlen + 1)
      nlen = buflen - 1;
    strncpy(cname, name, nlen);
    cname[nlen] = 0;
  }
  return retval;
}
Пример #5
0
int Sock_open(Sock_port_t port, Sock_error_t perr)
{
  int sock;
  struct sockaddr_in server;
 
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    return Sock_error(perr, errno, 0);
       
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = INADDR_ANY;
  server.sin_port = htons((short)port);
 
  if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) ||
      (listen(sock, MAXBACKLOG) < 0))
    return Sock_error(perr, errno, 0);
  return sock;
}
Пример #6
0
ssize_t Sock_write(int fd, void *buf, size_t size, Sock_error_t perr)
{
  ssize_t retval;
  do
    retval = send(fd, buf, size, 0);
  while (retval == -1 && errno == EINTR);
  if (retval == -1)
    return Sock_error(perr, errno, 0);
  else
    return retval;
}
Пример #7
0
/* write to a socket */
ssize_t Sock_write(int fd, const void *buf, size_t size, Sock_error_t perr)
{
#ifdef HAVE_SOCKETS
    ssize_t retval;
    do
	retval = send(fd, buf, size, 0);
    while (retval == -1 && errno == EINTR);
    if (retval == -1)
	return Sock_error(perr, errno, 0);
    else
	return retval;
#else
    error(socket_msg);
    return(-1);
#endif
}