(警告:我是这个东西的初学者。)
好的,我想我现在已经清楚地编写了代码。84 行。该代码不可移植。如果服务器是 linux x86_64,它只应该与 IPv4 一起使用。它应该使用 gcc 编译并开箱即用地运行。
下面启动一个接受单个客户端的 TCP 服务器。服务器有它的整数句柄 servSock,客户端有它的整数句柄 clntSock。该代码包含仅将这些整数句柄作为输入的函数,并以唯一整数形式(例如 iwhoareyou)或字符串形式(例如 swhoareyou)返回服务器和客户端 IP 地址。
我相信这段代码表现得很好,包括执行所有适当的清理代码。(它不会超时,但这并不重要,因为它会在客户端出现后立即关闭连接。没有接收或发送。)有时,它返回 0.0.0.0,有时它返回 127.0.0.1,但我相信这是正常行为.
如果仍然存在错误,即使是轻微的错误,请告诉我。在处理网络和许多进程时由于偏执狂......
#include <stdio.h> // printf, fprintf
#include <sys/socket.h> // socket, bind, connect
#include <arpa/inet.h> // sockaddr_in, inet_ntoa
#include <stdlib.h> // exit
#include <string.h> // strcpy, bzero
#include <unistd.h> // close
/****************************************************************/
#define IPNAMELEN 32
typedef char IPNAME[IPNAMELEN]; // must fit 4*4 + terminator
/****************************************************************/
static inline unsigned long iwho( const int clntSocket,
int (*function)(const int, struct sockaddr *, unsigned int *) ) {
struct sockaddr_in ipsock_in;
unsigned int cisl= sizeof(struct sockaddr_in);
if (getpeername( clntSocket, (struct sockaddr *)&ipsock_in, &cisl )) return 0;
return *((unsigned long *) (&ipsock_in.sin_addr));
}
static inline unsigned long iwhoareyou( const int clntSocket ) {
return iwho(clntSocket, getpeername ); }
static inline char *swhoareyou( const int clntSocket, IPNAME ipbuf ) {
unsigned long il= iwhoareyou(clntSocket);
return strcpy(ipbuf, inet_ntoa( *((struct in_addr *) (&il)) ));
}
static inline unsigned long iwhoami( const int servSocket ) {
return iwho(servSocket, getsockname ); }
static inline char *swhoami( const int servSocket, IPNAME ipbuf ) {
unsigned long il= iwhoareyou(servSocket);
return strcpy(ipbuf, inet_ntoa( *((struct in_addr *) (&il)) ));
}
/****************************************************************/
int main() {
const unsigned short ServPort=8081;
void die(char *s) { fputs(s, stderr); fputc('\n', stderr); exit(1); }
int servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (servSock<=0) die("cannot socket()");
struct sockaddr_in ServAddr;
bzero( &ServAddr, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServAddr.sin_port = htons(ServPort);
{
int yes=1; // tell the OS that we want to use it again
if (setsockopt(servSock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) die("cannot setsockopt");
}
if (bind(servSock, (struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0) die("cannot bind");
if (listen(servSock, 2) < 0) die("cannot listen");
struct sockaddr_in ClntAddr;
unsigned int clntLen = sizeof(ClntAddr);
int clntSock = accept(servSock, (struct sockaddr *) &ClntAddr, &clntLen);
if (clntSock < 0) die("cannot accept()");
printf("Server= %s.\n", inet_ntoa(ServAddr.sin_addr));
printf("Client= %s.\n", inet_ntoa(ClntAddr.sin_addr));
IPNAME buf;
printf("Via Function on clntSock: '%lu' and '%s'\n", iwhoareyou(clntSock), swhoareyou(clntSock, buf));
printf("Via Function on servSock: '%lu' and '%s'\n", iwhoami(servSock), swhoami(servSock, buf));
if (close(clntSock)) die("cannot close clnt");
if (close(servSock)) die("cannot close serv");
printf("Happy Ending\n");
return 0;
}