linxu套接字头文件:

#include <sys/socket.h>

创建套接字:

int socket(int domain,int type,int protocol);

domain:

AF_INET  IPv4

AF_INET6 IPv6

AF_UNIX Unix域

AF_UNSPEC 未指定

type:

SOCK_DGRAM 长度固定,无连接,不可靠传递 默认协议是UDP

SOCK_RAW ip协议的数据报接口

SOCK_SEQPACKET 长度固定,有连接,可靠的传递

SOCK_STREAM 有序,可靠,双向的连接字节流 默认协议是TCP

protocol:

一般为0,表示按给定的域和套接字类型选择默认协议

调用socket和open类似,均可以使用输入/输出文件描述符(但并非所有,例如lseek),不再使用时候用close关闭

可以使用shutdown禁止套接字上的输入输出

int shutdown(int sockfd,int how);

how:

SHUT_RD 关闭读端,无法从套接字上读取数据

SHUT_WR 关闭写端,无法从套接字上发送数据

SHUT_RDWR 无法读和写

关闭套接字:

close(int sockfd);

字节排序:

字节排序有两种,大端和小端,在32位机器上,大端排序为:n,n+1,n+2,n+3,小端排序为:n+3,n+2,n+1,n,但是不管字节排序如何,数字最高位总是在左边,最小位总是在右边,比如0x04030301,数字最高位必定是4,最低位必定是1

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostint32); 返回值:网络字节序表示的32位整数

uint16_t htons(uint16_t hostint16); 返回值:网络字节序表示的16位整数

uint32_t ntohl(uint32_t netint32);  返回值:主机字节序表示的32位整数

uint16_t ntohs(uint16_t netint16);  返回值:主机字节序表示的16位整数

记忆方法:

h=host,n=network,l=long(表示4个字节),s=short(表示两个字节);

注意:

有些系统将其定义在<netinet/in.h>

地址格式:

为使不同格式地址能够被传入套接字函数,地址被强制转换成sockaddr表示:

struct sockaddr

{

sa_family_t sa_family;

char sa_data[];

......

};

套接字可以自由添加额外成员并自定义sa_data的大小,在linxu中,被定义为:

struct sockaddr

{

sa_family_t sa_family;

char sa_data[14];

};

FreeBSD:

struct sockaddr

{

unsigned char sa_len;

sa_family_t sa_family;

char sa_data[14];

};

#include <netinet/in.h>

IPv4中(AF_INET)中,套接字地址结构为:

struct in_addr

{

in_addr_t s_addr;         in_addr_t为uint32_t

};

struct sockaddr_in

{

sa_family_t sin_family;

in_port_t sin_port;   in_port_t为uint16_t

struct in_addr  sin_addr;

};

uint32_t和uint16_t定义在<stdint.h>

IPv6(AF_INET6):

struct in6_addr

{

uint8_t s6_addr[16];

};

struct sockaddr_in6

{

sa_family_t sin6_family;

in_port_t sin6_port;

uint32_t sin6_flowinfo;

struct in6_addr sin6_addr;

uint32_t sin6_scope_id;

};

以上为必须定义,可以自由添加额外的字段:

struct sockaddr_in

{

sa_family_t sin_family;

in_port_t sin_port;

struct in_addr sin_addr;

unsigned char sin_zero[8];  //扩充字段,必须全部置为0

};

地址格式化:

#include <arpa/inet.h>

const char *inet_ntop(int doman,const void *restrict addr,char *restrict str,socklen_t size); 如果成功,返回地址字符串,否则返回NULL;

将网络字节序的二进制地址转换成文本字符串

size指定网络文本字符串缓冲区大小,INET4_ADDRSTRLEN和INET6定义足够大用来存放文本字符串

int inet_pton(int domain,const char *restrict str,void *rstrict addr); 如果成功返回1,无效返回0,出错返回-1

将文本字符串转换成网络字节序的二进制

如果domain是(AF_INET)IPv4,缓冲区addr有足够大存放32位地址,对于IPv6(AF_INET6),则需要足够大的空间存放128地址

以上两个函数均支持IPv4和IPv6,inet_addr和inet_ntoa仅支持IPv4

in_addr_t inet_addr(const char *cp);

char *inet_ntoa(struct in_addr in);

地址查询:

#include <netdb.h>

struct hostent *gethostent(void); 成功返回指针,失败NULL

打开数据文件,如果没有打开,会打开它

void sethostent(int stayopen);

如果没有打开,回绕

void endhostend(void);

关闭数据文件

struct hostent

{

char *h_name;

char **h_aliases;

int  h_addrtype;

int  h_lenght;

char **h_addr_list;

};

注意:返回的地址采用网络字节顺序

还有两个函数gethostbyname,gethostbyaddr,不过被认为是过时的,将会有替代函数

struct netent *getnetbyaddr(uint32_t net,int type);

struct netent *getnetbyname(const char *name);

struct netent *getnetent(void);

三个函数若成功返回指针,失败NULL

void setnetent(int stayopen);

void entnetent(void);

struct netent

{

char *n_name;

char **n_aliases;

int  n_addrtype;

uint32_t n_net;

.....

};

按照网络字节返回,n_addrtype是一个地址足常量(例如AF_INET);

可以将协议号采用以下函数映射:

struct protoent *getprotobyname(const char *name);

struct protoent *getprotobynumber(int proto);

struct protoent *getprotoent(void);

void setprotoent(int stayopen);

void endprotoent(void);

struct protoent

{

char *p_name;

char **p_aliases;

int  p_proto;

.....

};

getservebyname可以将一个服务名字映射到一个端口号,getservbyport反之,也可以采用getservent顺序扫描服务数据库;

struct servent *getservbyname(const char *name,const char *proto);

struct servent *getservbyport(int port,const char *proto);

struct servent *getservent(void);

void setservent(int stayopen);

void endservent(void);

struct servent

{

char *s_name;

char **s_aliases;

int  s_port;

char *s_proto;

.....

};

这几个函数代替gethostbyname和gethostbyaddr

#include <sys/socket.h>

#include <netdb.h>

int getaddrinfo(const char *restrict host,const char *restrict service,const struct addrinfo *restrict hint,struct addrinfo **restrict res);

成功返回0,出错返回非0

需要提供主机名字,服务名字,或者两者都提供,如果仅仅提供一个名字,另外一个必须使空指针,主机名字可以使一个节点名或者十进制计法表示的主机地址.

void freeaddrinfo(struct addrinfo *ai);

getaddrinfo返回一个addrinfo的链表,用freeaddrinfo释放.

struct addrinfo

{

int ai_flags;

int ai_family;

int ai_socktype;

int ai_protocol;

socklen_t ai_addrlen;

struct sockaddr *ai_addr;

char *ai_canonname;

struct addrinfo *ai_next;

.....

};

ai_flags:

AI_ADDRCONFIG 查询配置的地址类型(IPv4 or IPv6)

AI_ALL 查找IPv4 and IPv6 地址(仅用于AI_V4MAPPED)

AI_CANONNAME 需要一个规范名

AI_NUMERICHOST 数字格式返回主机地址

AI_NUMERICSERV 以端口号返回服务

AI_PASSIVE 套接字地址用于监听绑定

AI_V4MAPPED 如果没有IPv6,返回映射到IPv4的地址

PS:

如果getaddrinfo失败,不能用perror or strerror生成错误消息,替代调用gai_strerror将错误码转换错误消息

const char *gai_strerror(int error);

int getnameinfo(const struct sockaddr *restrict addr,socklen_t alen,char *restrict host,socklen_t hostlen,char *restrict service,socklen_t servlen,unsigned servlen,unsigned int flags);

将地址转换成主机名或者服务名

flags:

NI_DGRAM 服务基于数字报而非流

NI_NAMEREQD 如果找不到主机,作为一个错误对待

NI_NOFQDN 对于本地主机,仅返回完全限定域名的节点名字部分

NI_NUMERICHOST 数字形式返回主机地址

NI_NUMERICSERV  数字形式返回服务地址

代码

//示例代码:

#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void print_family(struct addrinfo *aip)
{
printf(" family ");
switch(aip->ai_family)
{
case AF_INET:
printf("inet");
break;
case AF_INET6:
printf("inet6");
break;
case AF_UNIX:
printf("unix");
break;
case AF_UNSPEC:
printf("unspecified");
break;
default:
printf("unknown");
}
}

void print_type(struct addrinfo *aip)
{
printf(" type ");
switch(aip->ai_socktype)
{
case SOCK_STREAM:
printf("stream");
break;
case SOCK_DGRAM:
printf("datagram");
break;
case SOCK_SEQPACKET:
printf("seqpacket");
break;
case SOCK_RAW:
printf("raw");
break;
default:
printf("unknown %d",aip->ai_socktype);
}
}

void print_protocol(struct addrinfo *aip)
{
printf(" protocol ");
switch(aip->ai_protocol)
{
case 0:
printf("default");
break;
case IPPROTO_TCP:
printf("TCP");
break;
case IPPROTO_UDP:
printf("UDP");
break;
case IPPROTO_RAW:
printf("raw");
break;
default:
printf("unknown %d",aip->ai_protocol);
}
}

void print_flags(struct addrinfo *aip)
{
printf(" flags ");
if(aip->ai_flags==0)
{
printf(" 0");
}
else
{
if(aip->ai_flags & AI_PASSIVE)
printf("passive");
if(aip->ai_flags & AI_CANONNAME)
printf(" canon ");
if(aip->ai_flags & AI_NUMERICHOST)
printf(" numhost ");
if(aip->ai_flags & AI_NUMERICSERV)
printf(" numserv");
}
}
int main(int argc,char *argv[])
{
struct addrinfo *ailist,*aip;
struct addrinfo hint;
struct sockaddr_in *sinp;
const char *addr;
int err;
char abuf[INET_ADDRSTRLEN];

if(argc != 3)
{
printf("%s nodename service",argv[0]);
return 1;
}
hint.ai_flags=AI_CANONNAME;
hint.ai_family=0;
hint.ai_socktype=0;
hint.ai_protocol=0;
hint.ai_addrlen=0;
hint.ai_canonname=NULL;
hint.ai_addr=NULL;
hint.ai_next=NULL;

if((err=getaddrinfo(argv[1],argv[2],&hint,&ailist)) !=0)
{
printf("error:%s\n",gai_strerror(err));
return 1;
}

for(aip=ailist;aip != NULL;aip=aip->ai_next)
{
print_flags(aip);
print_family(aip);
print_type(aip);
print_protocol(aip);
printf("\n\thost %s\n",aip->ai_canonname?aip->ai_canonname:"-");

if(aip->ai_family==AF_INET)
{
sinp=(struct sockaddr_in *)aip->ai_addr;
addr=inet_ntop(AF_INET,&sinp->sin_addr,abuf,INET_ADDRSTRLEN);
printf("address %s\n",addr?addr:"unknown");
printf("port %d",ntohs(sinp->sin_port));
}
printf("\n");
}
return 0;
}

转载于:https://www.cnblogs.com/linyilong3/archive/2010/10/09/1846259.html

Linux socket相关推荐

  1. Linux Socket基础介绍

    Linux Socket函数库是从Berkeley大学开发的BSD UNIX系统中移植过来的.BSD Socket接口是众多Unix系统中被广泛支持的TCP/IP通信接口,Linux下的Socket程 ...

  2. python封装api linux_python Socket编程-python API 与 Linux Socket API之间的关系

    python socket编程 by SA19225409 地址协议家族 Python 支持 AF_UNIX. AF_NETLINK. AF_TIPC 和 AF_INET 家族 AF_UNIX 基于本 ...

  3. linux socket关闭连接 shutdown与close

    在Linux socket关闭连接的方法有两种分别是shutdown和close,首先看一下shutdown的定义 #include<sys/socket.h>int shutdown(i ...

  4. Linux socket关闭连接shutdown与close

    在Linux socket关闭连接的方法有两种分别是shutdown和close,首先看一下shutdown的定义 #include<sys/socket.h> int shutdown( ...

  5. linux socket使用情况 ss -s ss -t -a | cat /proc/net/socketstat

    linux socket使用情况 ss -s ss -t -a | cat /proc/net/socketstat Linux系统中,查看SOCKET使用情况可以使用ss命令. 1.命令格式: ss ...

  6. 对于linux socket与epoll配合相关的一些心得记录

    对于linux socket与epoll配合相关的一些心得记录 没有多少高深的东西,全当记录,虽然简单,但是没有做过测试还是挺容易让人糊涂的 int nRecvBuf=32*1024;//设置为32K ...

  7. linux 查看socket fd,linux socket中select()函数以及FD_ZERO FD_SET FD_CLR FD_ISSET

    linux socket非阻塞编程时常见到如下的code: socket   s; ..... fd_set   set; ..... struct timeval tv; while(1) { FD ...

  8. linux socket高性能服务器处理框架

    这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765 思考一种高性能的服务器处理框架 1.首先需要一个内存池,目 ...

  9. Linux Socket详解 大全 基础知识

    1. Socket基础概念: 1.1:形象类比: Socket和电话网络的概念可以做一个很好的类比: Linux 编程中所说的socket就如同一个端点,类比到电话网中,它就如同一个电话机. 而Soc ...

  10. Linux Socket接口使用方法

    Linux内核net/socket.c定义了一套socket的操作api.图1展示了socket层所处与TCP/IP协议栈之上和应用层之下. socket()函数 socket函数对应于普通文件的打开 ...

最新文章

  1. 求二叉树某个结点的祖先
  2. Linux 查看Pyhont的解释器大小
  3. 【新年礼物】pmcaff会员大放送!
  4. CUDA函数库调用问题解决
  5. oracle 并行提交,如何配置Oracle并行处理(上)
  6. 洛谷 3398 仓鼠找sugar 【模板】判断树上两链有交
  7. Learning Perl chapter 4 练习题
  8. 10. HTML基本标签
  9. Win11怎么重置系统?Win11电脑重置系统的操作方法
  10. O_RDONLY/O_NOATIME undeclared (first use in this function
  11. Spring xml文件配置——创建bean的三种方式及作用范围、生命周期
  12. Linux服务器查看内存型号
  13. 文献翻译——基于关联规则挖掘识别的鸡源大肠杆菌共有多重耐药模式(上)
  14. ruby on rails中的分页插件Kaminari
  15. RTSP协议视频安防综合管理平台EasyNVR与海康萤石云平台运行机制差异对比说明
  16. 快速学习Java8新特性第七讲——Optional类
  17. springboot服务器没响应,记一次springboot 故障:接口无响应--》CPU 100%---》log无法写入---》磁盘满了...
  18. 漫画中国式项目管理重点总结
  19. 对你影响最深的计算机书籍是哪一本?
  20. 牛客网语法篇练习函数类型(全)

热门文章

  1. P2296 寻找道路
  2. 【SpringMVC学习05】SpringMVC中的参数绑定总结——较乱后期准备加入 同一篇幅他人的参数绑定...
  3. 实战MEF(4):搜索范围
  4. Anchor 对象学习
  5. 您已登录了一个相同的QQ账号,不能重复登录”的解决办法
  6. 数字的与或非处理表中的多个状态(二)
  7. 【Leetcode 687】递归求最大相同路径
  8. End-to-End Object Detection with Transformers的部分解读
  9. 洛谷P1411 砝码称重
  10. 轻量级ORM框架 Bankinate