|
Depending on the targer system you specified in the makefile, this file implements two functions:
- open_tcp_connexion
- Get_Sock_Adress
As you can see, we use conditional compilation depending on the target system (actually Windows or UNIX).
Generic macros defined in "sockets.h" make the functions' declarations system independent.
open_tcp_connexion()
The function open_tcp_connexion() opens a TCP connection to a server.
argument
| description |
tcp_host
| Host's name (or IP address) of the server's host. |
tcp_port
| Port number od the server. |
tcp_add
| This argument will receive the internet address os the server. |
timeout
| Timeout in seconds. If the function can not connect to the server before the end of the
timeout, then the function returns SCK_TIMEOUT_CONNECT.
|
Return value:
- SCK_OK: Success.
- SCK_CREATE_ERROR: Can not create socket. This means that the system call socket() failed.
- SCK_CONNECT_ERROR: Can not connect to the server. This means that the system call connect() failed.
- SCK_GET_IP_ERROR: Can not get the IP address associated with the host name. This means that the system call gethostbyname() failed.
- SCK_TIMEOUT_CONNECT: Can not connect to the server before the end of the timeout.
- SCK_SOCK_INIT_DLL_ERR: Can not initialize the winsock library (Windows only).
- SCK_SOCK_INIT_DLL_CHECK_ERR: Wrong winsock library's version.
- SCK_SET_NON_BLOCK_ERR: Can not set socket in non blocking mode.
- SCK_SET_BLOCK_ERR: Can not set socket in blocking mode.
Get_Sock_Adress
This function returns the server's internet address.
argument
| description |
Machine_serveur
| Server's IP address. |
port_serveur
| Server's port. |
TCP_address
| This argument receives the server's internet address.
|
Return value:
/******************************************************************************/
/* sockets.c: Socket management for TCP connexion */
/* */
/* Author: Denis BEURIVE. */
/******************************************************************************/
#include <errno.h>
#include "sockets.h"
#include <stdio.h>
/*****************************************************************************/
/* open_tcp_connexion */
/* */
/* -> tcp_host: Distant host (could be a host name or an IP address). */
/* -> tcp_port: Port number of the service to contact. */
/* <- tcp_add: Pointer to a structure unsed to save the Internet address. */
/* You probably don't need it, but sometimes you mist have it. */
/* -> timeout: timeout in seconds. */
/* */
/* RET: SCK_CREATE_ERROR => Can not create the socket. */
/* SCK_CONNECT_ERROR => Can not establish the connexion to the */
/* host. */
/* SCK_GET_IP_ERROR => gethostbyname() failed. This means that */
/* the system can not convert the host name */
/* into an IP address. */
/*****************************************************************************/
SOCK open_tcp_connexion (SOCK_IN *tcp_add, char *tcp_host, int tcp_port, int timeout)
{
SOCK desc;
int cr;
struct hostent *name;
char ip[16];
#if OS == WINDOWS_OS
u_long cmd_option;
DWORD start;
int last_error;
#endif
#if OS == UNIX_OS
int err;
#endif
#if OS == WINDOWS_OS
WORD wVersionRequested;
WSADATA wsaData;
#endif
/***************************************************************************/
/* For Windows only, initialize the "winsock" library. */
/***************************************************************************/
#if OS == WINDOWS_OS
wVersionRequested = MAKEWORD(2, 0);
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{ return SCK_SOCK_INIT_DLL_ERR; }
if ((LOBYTE( wsaData.wVersion ) != 2) ¦¦ (HIBYTE( wsaData.wVersion ) != 0) )
{
WSACleanup();
return SCK_SOCK_INIT_DLL_CHECK_ERR;
}
#endif
#ifdef DEBUG
fprintf (stdout, "\nopen_tcp_connexion: begin\n");
fprintf (stdout, "\nTCP host: %s\n", tcp_host);
fflush (stdout);
#endif
name = gethostbyname (tcp_host);
if (name == NULL)
{ return SCK_GET_IP_ERROR; }
#ifdef DEBUG
fprintf (stdout, "\nopen_tcp_connexion: gethostbyname() done\n");
fflush (stdout);
#endif
sprintf (ip, "%d.%d.%d.%d", (unsigned char)(name->h_addr_list)[0][0],
(unsigned char)(name->h_addr_list)[0][1],
(unsigned char)(name->h_addr_list)[0][2],
(unsigned char)(name->h_addr_list)[0][3]);
#ifdef DEBUG
fprintf (stdout, "\nopen_tcp_connexion: get the IP, done\n");
fflush (stdout);
#endif
desc = CREATE_SOCKET(AF_INET, SOCK_STREAM, 0);
if (desc == SCK_ERROR_SOCKET) { return (SCK_CREATE_ERROR); };
#ifdef DEBUG
fprintf (stdout, "\nopen_tcp_connexion: open socket, done\n");
fflush (stdout);
#endif
Get_Sock_Adress (ip, tcp_port, tcp_add);
#ifdef DEBUG
fprintf (stdout, "\nopen_tcp_connexion: Get_Sock_Adress(), done\n");
fflush (stdout);
#endif
/***************************************************************************/
/* Under Windows we use non blocking sockets to implement the "connect's */
/* timeout". */
/***************************************************************************/
#if OS == WINDOWS_OS
/***************************************************************************/
/* Set sockect in non blocking mode */
/***************************************************************************/
cmd_option = 1;
if (ioctlsocket (desc, FIONBIO, &cmd_option) == SOCKET_ERROR)
{ return SCK_SET_NON_BLOCK_ERR; }
/***************************************************************************/
/* Get start time */
/***************************************************************************/
cr = 1;
start = GetTickCount();
/***************************************************************************/
/* Loop until we connect or until timeout */
/***************************************************************************/
while (cr != 0)
{
#endif
/***************************************************************************/
cr = CONNECT_TO_SERVER(desc, tcp_add, sizeof(struct sockaddr_in));
/***************************************************************************/
#if OS == WINDOWS_OS
last_error = WSAGetLastError();
if (cr == SCK_ERROR_CONNECT)
{
if (
(last_error != WSAEWOULDBLOCK)
&&
(last_error != WSAEALREADY)
&&
(last_error != WSAEISCONN)
)
{ return SCK_CONNECT_ERROR; }
else
{
if (last_error == WSAEISCONN)
{
/*****************************************************************/
/* We set back the socket in blocking mode now and we return the */
/* socket's descriptor. */
/*****************************************************************/
cmd_option = 0;
if (ioctlsocket (desc, FIONBIO, &cmd_option) == SOCKET_ERROR)
{ return SCK_SET_BLOCK_ERR; }
return desc;
}
}
if ((GetTickCount() - start) > timeout*1000)
{ return SCK_TIMEOUT_CONNECT; }
}
}
#endif
/***************************************************************************/
/* Under UNIX, the system call "connect()" may be interrupted by the sig- */
/* -nal "SIGALRM". */
/***************************************************************************/
#if OS == UNIX_OS
err = errno;
if (cr == SCK_ERROR_CONNECT)
{
#if OS == UNIX_OS
if (err == EINTR) { return SCK_TIMEOUT_CONNECT; }
#endif
return SCK_CONNECT_ERROR;
}
#endif
return (desc);
};
/***************************************************************************/
/* Get_Sock_Adress */
/* */
/* Get the Internet address of a service from the following data: */
/* */
/* -> Machine_serveur : (in) Host IP address. */
/* -> port_serveur : (in) Port number. */
/* <- TCP_address : (out) service's address. */
/* */
/* RET: Always SCK_OK */
/***************************************************************************/
int Get_Sock_Adress (char *Machine_serveur, int port_serveur, SOCK_IN *TCP_address)
{
#ifdef DEBUG
fprintf (stdout, "\nGet_Sock_Adress: begin\n");
fflush (stdout);
#endif
memset ((void*)TCP_address, 0, sizeof(struct sockaddr_in));
TCP_address->sin_family = AF_INET;
TCP_address->sin_port = htons((u_short)port_serveur);
(TCP_address->sin_addr).s_addr = inet_addr(Machine_serveur);
#ifdef DEBUG
fprintf (stdout, "\nGet_Sock_Adress: end\n");
fflush (stdout);
#endif
return (SCK_OK);
}
|
|