套接字是通讯端点的抽象

创建一个套接字

#include <sys/types.h>
#include <sys/socket.h> int socket(int domain, int type, int protocol);
返回值:成功文件(套接字)描述符,失败-1
domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。
协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。
protocal:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等
它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

套接字通信是双向的。可以禁止一个套接字的I/O

#include <sys/socket.h>

int shutdown(int sockfd, int how);
返回值:成功0,出错-
sockfd:套接字的描述符
how:三种SHUT_RD()关闭sockfd上的读功能
SHUT_WR()关闭sockfd上的写功能
SHUT_RDWR()关闭sockfd的读写功能

用来在处理器字节序和网络字节序之间实施转换的函数

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);
返回值:以网络字节序表示的32位整数
uint16_t htons(uint16_t hostshort);
返回值:以网络字节序表示的16位整数
uint32_t ntohl(uint32_t netlong);
返回值:以主机字节序表示的32位整数
uint16_t ntohs(uint16_t netshort);
返回值:以主机字节序表示的16位整数

h表示主机字节序,n表示网络字节序,l表示长整型,s表示短整型

打印出能被人理解而不是计算机所理解的地址格式。同时支持IPv4和IPv6地址

#include <arpa/inet.h>

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
返回值:成功地址字符串指针,出错NULL
af:地址簇,仅支持AF_INET和AF_INET6
src:来源地址结构指针
dst:接收转换后的字符串
size:保存文本字符串的缓冲区大小 int inet_pton(int af, const char *src, void *dst);
返回值:成功1,格式无效0,出错-
af:地址簇,仅支持AF_INET和AF_INET6
src:转换的地址字符串
dst:转换后的地址结构指针

这个很常用,所有使用socket都需要用这两个函数转换,p应该是protocol,n应该是net吧。

例子

 #include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h> int main(int argc, char *argv[])
{
char dst[];
int sockfd = socket(AF_INET, SOCK_STREAM, ); struct sockaddr_in serv;
memset(&serv, ,sizeof(struct sockaddr_in)); serv.sin_family = AF_INET;
serv.sin_port = htons(); if((inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr)) == )
printf("inet_pton error\n");
if((inet_ntop(AF_INET, &serv.sin_addr.s_addr, dst, sizeof(dst))) == NULL)
printf("inet_ntop error\n");
printf("dst=%s,sizeof(dst)=%d\n", dst, sizeof(dst)); bind(sockfd, (struct sockaddr *)&serv, sizeof(serv));
listen(sockfd, );
return ;
}

inet_pton

找到给定计算机系统的主机信息

#include <netdb.h>

struct hostent *gethostent(void);
返回值:成功返回指针,出错NULL void sethostent(int stayopen);
stayopen:true就是TCP,否则UDP void endhostent(void);

能够采用一套相似的接口来获得网络名字和网络编号

#include <netdb.h>

struct netent *getnetbyaddr(uint32_t net, int type);
struct netent *getnetbyname(const char *name);
struct netent *getnetent(void);
返回值:成功返回指针,出错NULL void setnetent(int stayopen);
void endnetent(void);

在协议名字和协议编号之间进行映射

#include <netdb.h>

struct protoent *getprottobyname(const char *name);
struct protoent *getprotobynumber(int proto);
struct protoent *getprotoent(void);
返回值:成功返回指针,出错NULL void setprotoent(int stayopen);
void endprotoent(void);

服务是由地址的端口号部分表示的,每个服务由一个唯一的众所周知的端口号来支持。可以使用getservbyname将一个服务名映射到一个端口号,使用函数getservbyport将一个端口号映射到一个服务名,使用函数getservent顺序扫描服务数据库。

#include <netdb.h>

struct servent *getservbyname(const char *name, const char *proto);
struct servent *getservbyport(int port, const char *proto);
struct servent *getservent(void);
返回值:成功返回指针,出错NULL void setservent(int stayopen);
void endservent(void);

将一个主机和一个服务名映射到一个地址

#include <sys/socket.h>
#include <netdb.h> int getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
返回值:成功0,出错非0错误码
node:向一个主机名(域名)或者地址串(IPv4的点分十进制串或者IPv6的16进制串)。
service:指向一个服务名或者10进制端口号数串。
hints:可以是一个空指针,也可以是一个指向某个addrinfo结构的指针
res:指向的变量已被填入一个指针,它指向的是由其中的ai_next成员串联起来的addrinfo结构链表 void freeaddrinfo(struct addrinfo *res);

addrinfo结构体

struct addrinfo
{
int ai_flags;
int ai_family; //AF_INET,AF_INET6,UNIX etc
int ai_socktype; //STREAM,DATAGRAM,RAW
int ai_protocol; //IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc
size_t ai_addrlen;//length of ai_addr
char* ai_canonname; //full hostname
struct sockaddr* ai_addr; //addr of host
struct addrinfo* ai_next;
}

错误码需要调用函数来转换成错误消息

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h> const char *gai_strerror(int errcode);

将一个地址转换成一个额主机名和一个服务名

#include <sys/socke.h>
#include <netdb.h> int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);
返回值:成功0,出错非0值
sa:指向包含协议地址的套接口地址结构,它将会被转换成可读的字符串,
salen:结构的长度,这个结构长度通常由accept、recvfrom、getsockname、getpeername
host:主机字符串
hostlen:长度
serv:服务器字符串
servlen:长度
flags:标志位可以有多个用与或

sockaddr结构体

struct sockaddr

{
  unsigned short sa_family;  /*addressfamily,AF_xxx*/
  char sa_data[14];       /*14bytesofprotocoladdress*/
};

16-9.c

 #include "apue.h"
#if defined(SOLARIS)
#include <netinet/in.h>
#endif
#include <netdb.h>
#include <arpa/inet.h>
#if defined(BSD)
#include <sys/socket.h>
#include <netinet/in.h>
#endif 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 :
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 == ) {
printf("");
} 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");
if(aip->ai_flags & AI_V4MAPPED)
printf(" v4mapped");
if(aip->ai_flags & AI_ALL)
printf(" all");
}
} 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 != )
err_quit("usage: %s nodename service", argv[]);
hint.ai_flags = AI_CANONNAME;
hint.ai_family = ;
hint.ai_socktype = ;
hint.ai_protocol = ;
hint.ai_addrlen = ;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if((err = getaddrinfo(argv[], argv[], &hint, &ailist)) != )
err_quit("getaddrinfo error %s", gai_strerror(err));
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", 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", addr?addr:"unknown");
printf(" port %d", ntohs(sinp->sin_port));
}
printf("\n");
}
exit();
}

getaddrinfo

linux IPC socket的更多相关文章

  1. Linux IPC socket 广播,组播

    getsockopt()/setsockopt() //获得sockfd指向的socket的属性 int getsockopt(int sockfd, int level, int optname, ...

  2. Linux IPC socket编程基础

    头文件 #include<unistd.h> #include <sys/types.h> #include <sys/socket.h> #include< ...

  3. linux IPC socket(3)server简单写法

    写server的一些流程总结 一.向内核申请一个socket TCP形式 sock_fd = socket(AF_INET, SOCK_STREAM, ); UDP形式 sfd = socket(AF ...

  4. linux IPC socket(2)

    使用bind来关联地址和套接字 #include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, cons ...

  5. Linux IPC实践(1) -- 概述

    进程的同步与互斥 进程同步: 多个进程需要相互配合共同完成一项任务. 进程互斥: 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥;系统中某些 ...

  6. linux系统socket通信编程详解函数

    linux socket编程之TCP与UDP   TCP与UDP区别 TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之 ...

  7. linux ipc/its

    linux进程间双向消息队列 server.c #include <stdio.h> #include <stdlib.h> #include <string.h> ...

  8. linux中socket的理解

    对linux中socket的理解 一.socket 一般来说socket有一个别名也叫做套接字. socket起源于Unix,都可以用“打开open –> 读写write/read –> ...

  9. linux 客户端 Socket 非阻塞connect编程

    开发测试环境:虚拟机CentOS,windows网络调试助手        非阻塞模式有3种用途        1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...

随机推荐

  1. python3 实现简单ftp服务功能(服务端 For Linux)

    转载请注明出处! 功能介绍: 可执行的命令: lspwdcd put rm get mkdir 1.用户加密认证 2.允许多用户同时登陆 3.每个用户有自己的家目录,且只可以访问自己的家目录 4.运行 ...

  2. Quartz.Net 任务调度之特性(3)

    再实现类中使用,就是继承IJob的类 [PersistJobDataAfterExecution] //执行后的保留作业数据,链式传参(上一次的任务数据) [DisallowConcurrentExe ...

  3. 深入理解java虚拟机:笔记

    1.运行时数据区域 1.程序计数器 当前线程执行字节码的行号指示器,字节码解释器工作通过改变这个计数器的值来选取下一条需要执行的字节码指令,每一个线程拥有独立的程序计数器,线程私有的内存 2.虚拟机栈 ...

  4. java基础学习笔记四(异常)

    Java中的异常 Exception 如图可以看出所有的异常跟错误都继承与Throwable类,也就是说所有的异常都是一个对象. 从大体来分异常为两块: 1.error---错误 : 是指程序无法处理 ...

  5. PHP curl_multi_select函数

    curl_multi_select — 等待所有cURL批处理中的活动连接 说明 int curl_multi_select ( resource $mh [, float $timeout = 1. ...

  6. 彻底理解 JS 中 this 的指向

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  7. 探索Redis设计与实现15:Redis分布式锁进化史

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  8. linux教程及常用命令手册

    Linux 教程 Linux 教程.Linux 简介.Linux 安装.Linux 系统启动过程.Linux 系统目录结构.Linux 忘记密码解决方法.Linux 远程登录.Linux 文件基本属性 ...

  9. Ruby 技能图谱

    # Ruby 技能图谱 说明: 本图谱只捡重点的列举,并非包含全部.文中所列举或没有列举的资源信息都可以在[awesome-ruby](https://github.com/markets/aweso ...

  10. PHP面试 MySQL的SQL语句编写

    MySQL的SQL语句编写 面试题一 有A表(id,sex,par,c1,c2),B(id,age,c1,c2)两张表,其中A.id与B.id关联,现在要求写出一条SQL语句,将B中age>50 ...