📄 socket.c
字号:
/* camserv - An internet streaming picture application * * Copyright (C) 1999-2002 Jon Travis (jtravis@p00p.org) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/unistd.h>#include <fcntl.h>#include "socket.h"#define BAD_SOCKET -1#define BAD_PORT -1#define MAX_SOCKET_REMOTE_NAME 512struct socket_st { int fd; char remote_name[ MAX_SOCKET_REMOTE_NAME ]; /* hostname of remote */ short port;};/* * socket_zero: Zero out a socket structure * * Arguments: sock = Socket to zero out */ void socket_zero( Socket *sock ){ sock->fd = BAD_SOCKET; sock->port = BAD_PORT; strcpy( sock->remote_name, "** Disconnected **" );}/* * socket_new: Create a new socket structure and initialize it * * Return values: Returns NULL on failure, else a valid pointer to a new * socket. */Socket *socket_new(){ Socket *res; if( (res = malloc( sizeof( *res ))) == NULL ) return NULL; socket_zero( res ); return res;}/* * socket_dest: Destroy a previously allocated socket * * Arguments: sock = socket to destroy */void socket_dest( Socket *sock ){ if( sock->fd >= 0 ) close( sock->fd ); free( sock );}/* * socket_query_remote_name: Get the remote IP address connected to the sock * * Arguments: sock = Socket to get the remote IP of * * Return values: Returns the remote name */const char *socket_query_remote_name( Socket *sock ){ return sock->remote_name;}/* * socket_query_fd: Get the FD associated with a socket * * Arguments: sock = Socket to get the FD of * * Return values: Returns the FD of the sock, or -1 if the fd is invalid. */ int socket_query_fd( const Socket *sock ){ return sock->fd;}/* * socket_set_remote_name: Set the remote name of a socket * * Arguments: sock = Socket to set the name of * new_name = New name for the socket */staticvoid socket_set_remote_name( Socket *sock, const char *new_name ){ strncpy( sock->remote_name, new_name, sizeof( sock->remote_name ) -1 ); sock->remote_name[ sizeof( sock->remote_name ) - 1 ] = '\0';}/* * socket_resolv_hostname: Resolve a string hostname to a internet sockaddr * structure * * Arguments: hname = Hostname to resolve. * sin = Sockaddr struct to place resolved host * * Return values: Returns -1 on failure, 0 on succes. */staticint socket_resolv_hostname( const char *hname, struct sockaddr_in *sin ){ struct hostent *hostp; unsigned long addr; addr = inet_addr( hname );#ifdef INADDR_NONE if( addr != INADDR_NONE ) memcpy( &sin->sin_addr, &addr, sizeof( addr ));#else if (addr != (in_addr_t)-1) memcpy( &sin->sin_addr, &addr, sizeof( addr ));#endif else { hostp = gethostbyname( hname ); if( hostp == NULL ) return -1; else memcpy( &sin->sin_addr, hostp->h_addr, hostp->h_length ); } return 0;}/* * socket_unix_pair_dest: Destroy a previously created socket pair * * Arguments: sockpar = Sockpair to destroy */void socket_unix_pair_dest( Socket **sockpair ){ socket_dest( sockpair[ 0 ] ); socket_dest( sockpair[ 1 ] ); free( sockpair );}/* * socket_unix_pair: Create a UNIX socket pair */Socket **socket_unix_pair( int type ){ Socket **res; int resfd[2]; if( (res = malloc( sizeof( *res ) * 2 )) == NULL ) return NULL; if( (res[ 0 ] = socket_new()) == NULL || (res[ 1 ] = socket_new()) == NULL ) return NULL; if( socketpair( PF_UNIX, type, 0, resfd ) == -1 ) { socket_dest( res[ 0 ] ); socket_dest( res[ 1 ] ); free( res ); return NULL; } socket_set_remote_name( res[ 0 ], "Local Unix Socket" ); socket_set_remote_name( res[ 1 ], "Local Unix Socket" ); res[ 0 ]->fd = resfd[ 0 ]; res[ 1 ]->fd = resfd[ 1 ]; return res;}/* * socket_serve_tcp: Createa new socket which serves as a listening socket. * * Arguments: hname = hostname to bind to. One can bind to only * listening to a certain address, or NULL can be * passed in to listen to all addys * port = Port number to listen on * backlog = Backlog arg to listen() * * Return values: Returns NULL on failure, else a valid listen sock on * success */Socket *socket_serve_tcp( const char *hname, int port, int backlog ){ Socket *sockres; struct sockaddr_in sin; int val; if( (sockres = socket_new()) == NULL ) return NULL; sockres->port = port; if( (sockres->fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0 ){ perror( "socket()" ); socket_dest( sockres ); return NULL; } sin.sin_family = AF_INET; sin.sin_port = htons( port ); if( hname == NULL ) { sin.sin_addr.s_addr = INADDR_ANY; socket_set_remote_name( sockres, "Any Host" ); } else { socket_set_remote_name( sockres, hname ); if( socket_resolv_hostname( hname, &sin ) == -1 ) { socket_dest( sockres ); return NULL; } } val = 1; if( setsockopt( sockres->fd,SOL_SOCKET,SO_REUSEADDR, &val, sizeof( int )) <0) perror( "setsockopt()" ); val = 1; if( setsockopt( sockres->fd,SOL_SOCKET,SO_KEEPALIVE, &val, sizeof( int )) <0) perror( "setsockopt()" ); if( bind( sockres->fd, (struct sockaddr *)&sin, sizeof( sin )) < 0 ) { perror( "bind()" ); socket_dest( sockres ); return NULL; } if( listen( sockres->fd, backlog ) < 0 ) { perror( "close()" ); socket_dest( sockres ); return NULL; } return sockres;}/* * socket_access: Accept a connection on a listen sock, and create a new * socket for the new connection. * * Arguments: listen_sock = Listen sock as setup by socket_serve_tcp * * Return values: Returns a new socket representing the new connection on * success, and NULL on failure. */Socket *socket_accept( const Socket *listen_sock ){ Socket *new_socket; struct sockaddr saddr; struct sockaddr_in *sin; unsigned int addrlen = sizeof( saddr ); int accres; if( (accres = accept( listen_sock->fd, &saddr, &addrlen )) == -1 ) return NULL; if( (new_socket = socket_new()) == NULL ) return NULL; sin = (struct sockaddr_in *)&saddr; new_socket->fd = accres; new_socket->port = sin->sin_port; socket_set_remote_name( new_socket, inet_ntoa( sin->sin_addr )); return new_socket;}/* * socket_connect: Connect to a remote socket, and return a new connection * object. * * Arguments: remote_name = Remote hostname to connect to * remote_port = Remote port to connect to * * Return values: Returns NULL on failure, else a valid pointer to a new * socket structure. */Socket *socket_connect( const char *remote_name, int remote_port ){ Socket *res; struct sockaddr_in sin; if( (res = malloc( sizeof( *res ))) == NULL ) return NULL; res->port = remote_port; if( (res->fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0 ){ perror( "socket()" ); socket_dest( res ); return NULL; } sin.sin_family = AF_INET; sin.sin_port = htons( remote_port ); if( socket_resolv_hostname( remote_name, &sin ) == -1 ){ socket_dest( res ); return NULL; } if( connect( res->fd, (struct sockaddr *)&sin, sizeof( sin )) == -1 ){ perror( "connect()" ); socket_dest( res ); return NULL; } socket_set_remote_name( res, remote_name ); return res;}int socket_set_nonblock( Socket *sock ){ if( fcntl( socket_query_fd( sock ), F_SETFL, O_NONBLOCK ) == -1) return -1; else return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -