首先列举所需要的头文件
#include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <assert.h> #include <string.h> #include <arpa/inet.h> #include <stdio.h> #include <netdb.h> /************************************** 函数名:CreateSock 参数: pSock:回传创建的侦听套接字描述符 nPort:指定套接字侦听端口 nMax:该套接字最大连接数 函数功能:封装套接字的创建、命名和侦听 返回值:0 **************************************/ int CreateSock(int *pSock, int nPort , int nMax) { struct sockaddr_in addrin; struct sockaddr *paddr = (struct sockaddr*)&addrin; assert(pSock != NULL && nPort > 0 && nMax > 0); memset(&addrin, 0,sizeof(addrin)); addrin.sin_family = AF_INET; addrin.sin_addr.s_addr = htonl(INADDR_ANY); addrin.sin_port = htons(nPort); /*创建TCP套接字描述符*/ *pSock = socket(AF_INET, SOCK_STREAM, 0); /*命名套接字*/ bind(*pSock, paddr, sizeof(addrin)); /*进入侦听状态*/ listen(*pSock, nMax); return 0; } /************************************** 函数名:AcceptSock 参数: pSock:创建的新的套接字描述符与客户 进程通信 nSock:accept成功后依然用于套接字侦听 函数功能:接受客户端的套接字连接申请 返回值:0 **************************************/ int AcceptSock(int *pSock, int nSock) { struct sockaddr_in addrin; int lSize; assert(pSock != NULL && nSock > 0); while(1) { lSize = sizeof(addrin); memset(&addrin, 0, sizeof(addrin)); if((*pSock = accept(nSock, (struct sockaddr*)&addrin, &lSize)) > 0) return 0; else assert(0); } } /************************************** 函数名:LocateRemoteAddr 参数: nSock:本地与用户通信的套接字描述符 pAddr:缓冲区,用来存储客户端IP地址 函数功能:获取与本地通信的客户端IP地址 返回值: 成功:0 失败:-1 **************************************/ int LocateRemoteAddr(int nSock, char *pAddr) { struct sockaddr_in addrin; int lSize; /*将addrin结构清零*/ memset(&addrin, 0, sizeof(addrin)); lSize = sizeof(addrin); if(getpeername(nSock, (struct sockaddr *)&addrin, &lSize) >= 0) { strcpy(pAddr,inet_ntoa(addrin.sin_addr)); return 0; } else return -1; }
一、Socket的域名地址
这里实现一个功能,即将域名转化为IP地址,并以字符串的形式输出。
使用到的函数:struct hostent *gethostbyname(const char *name);
参数:想要查询的IP对应的域名
返回值:
成功:指向hostent结构的指针
失败:NULL
/************************************** 文件名:tcp2.c Author:Bumble Bee 日期:2015-3-24 文件说明:已知网站IP,获取其域名,域名 通过命令行输入 **************************************/ #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <stdio.h> #include <netdb.h> int main(int argc, char **argv) { struct hostent *host; if(argc != 2) { printf("please enter host name\n"); return 1; } if((host = gethostbyname(argv[1])) == NULL) { herror("gethostbyname"); return 2; } printf("Host name is %s\n", host->h_name); printf("Host IP is %s\n", inet_ntoa((host->h_addr))); return 0; }
二、Socket端口
Linux提供了很多网络服务进程,每个进程都会占用一个TCP端口在后台进行套接字侦听,一般情况系统占用小于1024的端口号。这里实现通过系统服务进程查看端口号和通过端口号查看系统服务进程。
使用函数:struct servent *getservbyname(const char *name, const char *proto);
struct servent *getservbyport(int port, const char *proto);
参数:
name:服务进程的名称
proto:该服务使用协议定名称
port:端口号
返回值:
成功:指向结构servent的指针
失败:NULL
通过系统服务进程查看端口号
/************************************** 文件名:tcp4.c Author:Bumble Bee 日期:2015-3-25 文件说明:通过系统服务进程查看端口号 **************************************/ #include "socket.h" int main(int argc, char **argv ) { struct servent *serv; if(argc != 2) return 1; if((serv = getservbyname(argv[1],"tcp")) == NULL) { herror("getsercbyname"); return 2; } printf("Serv name :%s\n",serv->s_name ); printf("Serv Port :%d\n",ntohs(serv->s_port)); return 0; }
通过端口号查看系统服务进程
/************************************** 文件名:tcp2.c Author:Bumble Bee 日期:2015-3-25 文件说明:通过端口号查看系统服务进程 **************************************/ #include "socket.h" int main(int argc, char **argv ) { struct servent *serv; if(argc != 2) return 1; if((serv = getservbyport(htons(atoi(argv[1])), "tcp"))== NULL) //使用网络字节序,而且要将字符串转换为整形数字 { herror("getsercbyport"); return 2; } printf("Serv name :%s\n",serv->s_name ); printf("Serv Port :%d\n",ntohs(serv->s_port)); return 0; }
三、Socket的协议地址
当本地套接字与远程建立连接后,就可以获取双方的IP地址。这里介绍获取远程客户端的IP地址。
使用函数:int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
sockfd:本地建立连接使用的套接字描述符
addr:与sockfd连接的套接字协议地址信息
addrlen:addr结构的长度
为了提高代码重用度,我们在此将getpeername函数进行封装,代码如下:
/************************************** 函数名:LocateRemoteAddr 参数: nSock:本地与用户通信的套接字描述符 pAddr:缓冲区,用来存储客户端IP地址 函数功能:获取与本地通信的客户端IP地址 返回值: 成功:0 失败:-1 **************************************/ int LocateRemoteAddr(int nSock, char *pAddr) { struct sockaddr_in addrin; int lSize; /*将addrin结构清零*/ memset(&addrin, 0, sizeof(addrin)); lSize = sizeof(addrin); if(getpeername(nSock, (struct sockaddr *)&addrin, &lSize) >= 0) { strcpy(pAddr,inet_ntoa(addrin.sin_addr)); return 0; } else return -1; }
这里实现功能:获取与本地通信的远程端IP地址并输出。
/************************************** 文件名:tcp5.c Author:Bumble Bee 日期:2015-3-26 文件说明:获取与本地通信的客户端IP地址 **************************************/ #include "socket.h" int main() { int nSock, pSock; char szAddr[30]; if(CreateSock(&nSock,9001,9) !=0) return 0; AcceptSock(&pSock,nSock); LocateRemoteAddr(pSock,szAddr); fprintf(stderr, "ip is %s\n", szAddr); close(pSock); close(nSock); }
执行该程序后,该进程进入阻塞态,等待用户与其通信。
我们在win下打开命令行,使用telnet IP地址 端口号 与linux通信。
这次就记录到这里,如果有疑问或错误,欢迎指出