Socket 函数库 (转载)

Socket 函数库
--------------------------------------------------------------------------------
相关函数:socket, bind, listen, connect
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int accept(int s, struct sockaddr *addr, int *addrlen)
函数说明:accept()用来接受参数s的socket连线。
参数s的socket必需先经bind()、listen()函数处理过,当有连线进来时accept()会返回一个新的socket处理代码,往后的数据传送与读取就是经由新的socket处理,而原来参数s的socket能继续使用accept()来接受新的连线要求。连线成功时,参数addr所指的结构会被系统填入远程主机的地址数据,参数addrlen为sockaddr的结构长度。
返回值  :成功则返回socket处理代码, 失败则返回-1, 错误原因存于errno中
错误代码:EBADF                      参数s非合法socket处理代码
               EFAULT                    参数addr指针指向无法存取的内存空间
               ENOSTOCK               参数s为一文件描述词,非socket        
               EOPNOTSUPP           指定的socket并非SOCK_STREAM
               EPERM                      防火墙(firewall)拒绝此连线
               ENOBUFS                  系统的缓冲内存不足
               ENOMEM                   核心内存不足

范例:请参listen()
 bind对socket定位


--------------------------------------------------------------------------------
相关函数:socket, accept, connect, listen
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
函数说明:bind()用来设置给参数sockfd的socket一个名称。此名称由参数my_addr指向一sockaddr结构, 对于不同的socket domain定义了一个通用的数据结构:

struct  sockaddr{
         unsigned  short  int  sa_family;   /* 为调用socket()的domain参数,即AF_xxxx值 */
         char  sa_data[14];  /* 最多使用14个字符长度  */
};

/*******************************************************/

AF 表示ADDRESS FAMILY 地址族
PF 表示PROTOCL FAMILY 协议族
但这两个宏定义是一样的
所以使用哪个都没有关系

Winsock2.h中
#define AF_INET 0
#define PF_INET AF_INET

所以在windows中AF_INET与PF_INET完全一样

而在Unix/Linux系统中,在不同的版本中这两者有微小差别

对于BSD,是AF,对于POSIX是PF

在函数socketpair与socket的domain参数中有AF_UNIX,AF_LOCAL,AF_INET,PF_UNIX,PF_LOCAL,PF_INET.
这几个参数有AF_UNIX=AF_LOCAL, PF_UNIX=PF_LOCAL, AF_LOCAL=PF_LOCAL, AF_INET=PF_INET.
**建议:对于socketpair与socket的domain参数,使用PF_LOCAL系列,
而在初始化套接口地址结构时,则使用AF_LOCAL.
例如:
    
z = socket(PF_LOCAL, SOCK_STREAM, 0);
     adr_unix.sin_family = AF_LOCAL;
/*******************************************************************/

此sockaddr结构会因使用不同的socket domain而有不同结构的定义,例如使用AF_INET domain, 其sockaddr结构定义便为:
struct socketadd_in
{
     unsigned short int sin_family;   /*  即为sa_family */
     uint16_t  sin_port;                 /* 为使用的port编号 */
     struct  int_addr sin_addr;        /* 为IP地址 */
     unsigned char sin_zero[8];      /* 未用 */
};


struct in_addr
{
      uint32_t  s_addr;
};


参数addrlen为sockaddr的结构长度

返回值   :成功则返回0,  失败则返回-1, 错误原因存于errno中

错误代码:EBADF            参数sockfd非合法socket处理代码
               EACCESS        权限不足
               ENOTSOCK     参数sockfd为一文件描述词,非socket

范例: 参listen()
connect建立socket连线


--------------------------------------------------------------------------------
相关函数:socket, bind, listen
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
函数说明:connect()用来将参数sockfd的socket连到参数serv_addr指定的网络地址。结构sockaddr请参bind()
返回值   :成功则返回0, 失败返回-1, 错误原因存于errno中
错误代码:EBADF        参数sockfd非合法socket处理代码
               EFAULT      参数serv_addr指针指向无法存取的内存空间
               ENOTSOCK 参数sockfd为一文件描述词,非socket
               EISCONN    参数sockfd的socket已是连线状态
               ECONNREFUSED  连线要求被server端拒绝
               ETIMEDOUT        企图连线的操作超过限定时间仍未有响应
               ENETUNREACH     sockaddr结构的sa_family不正确
               EALREADY           socket为不可阻断且先前的连线操作还未完成

范例:
/*
  利用socket的TCP client
   此程序会连线TCP server,并将键盘输入的字符串传送给server
   TCP server范例请参考listen()
*/

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define  PORT    1234         /* 使用的port号码 */
#define SERVER_IP    "127.0.0.1"   /* SERVER 的IP*/

main()
{
    int s;
    struct sockaddr_in  addr;
    char buffer[256];
    if((s = socket(AF_INET, SOCK_STREAM, 0)) <0) {
        perror("socket");
        exit(1);
    }
  
    /*填写sockaddr_in 结构*/
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr= inet_addr(SERVER_IP);
   
     /* 尝试连线 */
     if(connect(s, &addr, sizeof(addr))<0) {
           perror("connect");
           exit(1);
      }

     /* 接收由server端传来的信息 */
     recv(s, buffer, sizeof(buffer), 0);
     printf("%s\n", buffer);
     while(1){
             bzero(buffer, sizeof(buffer));
         
             /*  从标准输入设备取得字符串 */    
             read(STDIN_FILENO, buffer, sizeof(buffer));

             /* 将字符串传送给server端 */
             if(send | s, buffer, sizeof(buffer), 0) <0) {
                      perror("send");
                      exit(1);
              }
        }

}
endservent结束网络服务数据的读取


--------------------------------------------------------------------------------
相关函数:getservent, getservbyname, getservbyport, setservent
表头文件:#include <netdb.h>
函数定义:void endservent(void)
函数说明:endservent()用来关闭由getservent()所打开的文件
返回值   :无
范例:参getservent()
endprotoent结束网络协议数据的读取


--------------------------------------------------------------------------------
相关函数:getprotoent, getprotobyname, getprotobynumber, setprotoent
表头文件:#include <netdb.h>
函数定义:void endprotoent(void)
函数说明:endprotoent()用来关闭由getprotoent()所打开的文件
返回值   :无
范例       :参getprotoent()
gethostbyname由主机名称取得网络数据


--------------------------------------------------------------------------------
相关函数:gethostbyaddr, sethostent
表头文件:#include <netdb.h>
函数定义:struct hostent  *gethostbyname(const char *name)
函数说明:gethostbyname()会返回一个hostent结构,参数name可以为一个主机名或IPv4/IPv6的IP地址。
struct  hostent
{
    char *h_name;           /*正式的主机名称*/
    char **h_aliases;        /* 指向主机名称的其他别名 */
    int h_addrtype;          /* 地址的型态, 通常是AF_INET */
    int h_length;             /*地址的长度*/
    char **h_addr_list;     /* 从域名服务器取得该主机的所有地址 */
};

返回值 :成功返回hostent结构指针,失败则返回NULL指针, 错误原因存于h_errno变量中
错误代码:
                HOST_NOT_FOUND                找不到指定的主机
                NO_ADDRESS                        该主机有名称却无IP地址
                NO_RECOVERY                      域名服务器有错误发生
                TRY_AGAIN                           请再调用一次
范例:
/*得用gethostbyname()的简单反查IP程序*/          
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include  <arpa/inet.h>

int main(int argc, char *argv[])
{
     struct hostent *hp;
     struct in_addr  in;
     struct sockaddr_in  local_addr;
    
     if(argc<2) return;
     if(!(hp=gethostbyname(argv[1]))) {
             fprintf(stderr, "Can't resolve host.\n");
             exit(1);
     }
    
     memcpy(&local_addr.sin_addr.s_addr, hp->h_addr, 4);
     in.s_addr= local_addr.sin_add.s_addr;
     printf("Domain Name:%s \n", argv[1]);
     printf("IP Address: %s\n", inet_ntoa(in));

}
gethostbyaddr由IP地址取得网络数据


--------------------------------------------------------------------------------
相关函数:gethostbyname
表头文件:#inlcude <netdb.h>
函数定义:struct  hostent  *gethostbyaddr(const char *addr, int len, int type)
函数说明:gethostbyaddr()会返回一个hostent结构,参数addr可以为IPv4或IPv6的IP地址,参数len为参数addr的长度,参数type为AF_INET。结构hostent定义请参gethostbyname()
返回值   :成功则返回hostent结构指针, 失败则返回NULL指针,错误原因存于h_errno变量
错误代码:HOST_NOT_FOUND    找不到指定的主机
               NO_ADDRESS             该主机有名称却无IP地址
               NO_RECOVERY           域名服务器有错误发生
               TRY_AGAIN               请再调用一次

范例:
#include <netdb.h>
#include <sys/socket.h>

main(int argc, char *argv[])
{
    struct hostent  *host;
    if(argc<2) return;
    host = gethostbyaddr(argv[1], sizeof(argv[1]), AF_INET);
    if(host == (struct hostent * ) NULL)
         herror("gethostbyaddr");
    else{
           printf("name :%s\n",  host->h_name);
           printf("type  :%s\n", host->h_addrtype);
           printf("addr  :%s\n", host->h_addr_list[0]);
    }
        
}
getprotobyname由网络协议名称取得协议数据


--------------------------------------------------------------------------------
相关函数:getprotobynumber, getprotoent, setprotoent, endprotoent
表头文件:#include <netdb.h>
函数定义:struct protoent *getprotobyname(const char *name)
函数说明:getprotobyname()会返回一个protoent结构,参数name为欲查询的网络协议名称。此函数会从/etc/protocols中查找各个符合条件的数据并由结构protoent返回。结构构protoent定义参getprotoent()
返回值   :成功返回protoent结构指针, 失败或找不到符合的数据则返回NULL指针
范例:
/*取得icmp协议数据*/
#include <netdb.h>
main()
{
      struct protoent *protocol;
      protocol = getprotobyname("icmp");
      printf("protocol name :%s\n", protocol->p_name);
      printf("protocol number: %d\n", protocol->p_proto);
      printf("protocol alias : %s\n", protocol->p_aliases[0]);
}
getprotobynumber由网络协议号取得协议数据


--------------------------------------------------------------------------------
相关函数:getprotobyname, getprotoent, setprotoent, endprotoent
表头文件:#include <netdb.h>
函数定义:struct protoent *getprotobynumber(int proto)
函数说明:getprotobynumber()会返回一个protoent结构,参数proto为欲查询的网络协议编号。此函数会从/etc /protocols中查找符合条件的数据并由结构protoent返回。 结构protoent定义请参getprotoent()
返回值   :成功则返回protoent结构指印,若有错误或找不到各个符合的数据则返回NULL指针

范例:
/*取得协议编号0到4的协议数据*/

#include <netdb.h>
main()
{
    int number;
    struct protoent *protocol;
    for(number=0; number<5; number++)
   {
       protocol = getprotobynumber(number);
       if(protocol == (struct protoent * ) NULL) continue;
       printf("%2d: %-10s: %-10s\n", protocol->p_proto, protocol->p_name, protocol->p_aliases[0]);
   }
}
getservbyname依名称取得网络服务的数据


--------------------------------------------------------------------------------
相关函数:getservent, getservbyport, setservent, endservent
表头文件:#include <netdb.h>
函数定义:struct servent *getservbyname(const char *name, const char *proto)
函数说明:getservbyname()会返回一个servent结构,参数name可以为一个网络服务的名称,参数proto则为该服务所使用的协议。此函数会从/etc/services中查找符合条件的数据并由结构 servent返回。结构servent的定义参getservent()
返回值:成功则返回servent结构指针, 失败则返回NULL指针
范例:
#include <netdb.h>

main()
{
    struct servent  *s;
    s=getservbyname("telnet", "tcp");
    printf("%s %d/%s  \n", s->s_name, ntohs(s->s_port), s->s_proto);
}
getservbyport依port号码取得网服务的数据


--------------------------------------------------------------------------------
相关函数:getservent, getservbyname, setservent, endservent
表头文件:#include <netdb.h>
函数定义:struct servent *getservbyport(int prot, const char *proto)
函数说明:getservbyport()会返回一个servent结构,参数port可以为一个port号码,参数proto则为该服务所使用的协议。此函数会从/etc/services中查找符合条件的数据,并由结构servent返回。结构servent的定义请参考getservent()
附加说明:参数port必须先由htons()转换
返回值  :成功则返回servent结构指针, 若有错误则返回NULL指针
范例:
#include <netdb.h>
main()
{
    struct servent *s;
    s=getservbyport(htons(23), "tcp");
    printf("%s %d/%s\n", s->s_name, ntohs(s->s_port), s->s_proto);
}
getservent取得主机网络服务的数据


--------------------------------------------------------------------------------
相关函数:getservbyname, getservbyport, setservent, endservent
表头文件:#include <netdb.h>
函数定义:struct servent *getservent(void)
函数说明:getservent()会打开/etc/services, 然后读取一行数据后由结构servent返回。之后再调用此函数则会继续读取下项数据,除非已到文件尾时返回NULL指针。
struct servent
{
     char  *s_name;     /*服务名称*/
     char  **s_aliases;  /*别名列表*/
     int     s_port;       /*所使用的port号码*/
     char   *s_proto;   /*使用的协议名称*/
};

返回值  :成功则返回servent结构指针, 若有错误或读到了文件尾则返回NULL指针
范例:
/*列出主机所有网络服务的数据*/

#include <netdb.h>
main()
{   
     struct servent *s;
     while((s = getservent())
     {
           printf("%s %d/%s\n", s->s_name, ntobs(s->s_port), s->s_proto);
     }
     endservent();
}
getsockopt取得socket状态


--------------------------------------------------------------------------------
相关函数:setsockopt
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
函数说明:getsockopt()会将参数s所指定的socket状态返回。
参数optname代表欲取得何种选项状态
参数optval则指向欲保存结果的内存地址,
参数optlen则为该空间的大小
参数level、optname请参setsockopt()
错误代码:EBADF           参数s并非合法的socket处理代码
               ENOTSOCK     参数s为一文件描述词,非socket
               ENOPROTOOPT 参数optname指定的选项不正确
               EFAULT            参数optval指针指向无法存取的内存空间
范例:
include <sys/types.h>
inlcude <sys/socket.h>

main()
{
    int  s, optval, optlen=sizeof(int);
    if((s=socket(AF_INET, SOCK_STREAM, 0)) <0)
             perror("socket");
    getsockopt(s, SOL_SOCKET, SO_TYPE, &optval, &optlen);
    printf("optval = %d\n", optval);
    close(s);
}
getprotoent取得网络协议数据


--------------------------------------------------------------------------------
相关函数:getprotobyname, getprotobynumber, setprotoent, endprotoent
表头文件:#include <netdb.h>
函数定义:struct protoent *getprotoent(void)
函数说明:getprotoent()会打开/etc/protoclos,然后读取一行数据后由结构protoent返回。之后再调用此函数则会继续读取下一项数据,除非已到文件尾时返回NULL指针
结构protoent定义
struct protoent
{
    char *p_name;    /*official protocol name*/
    char **p_aliases; /*alias list*/
    char p_proto;     /*protocol number*/
};


返回值  :成功则返回protoent结构指针,有错或找不到符合的数据则返回NULL指针
范例:
/*取得所有协议数据*/
#include <netdb.h>

main()
{
    struct protoent *p;
    while(p=getprotoent())
     {
          printf("%s %s %d\n", p->p_name, p->aliases[0], p->p_proto);
     }  
     endprotoent();
}

hstrerror返回网络错误原因的描述字符串

--------------------------------------------------------------------------------
相关函数:herror
表头文件:#include <netdb.h>
函数定义:const char *hstrerror(int err)
函数说明:hstrerror()用来依参数err的错误代码来查询socket错误原因的描述字符串, 然后将该字符串指针返回
返回值   :返回描述错误原因的字符串指针
范例:
/*显示错误代码0到5的错误原因描述*/
#include <netdb.h>
main()
{
    int i;
    for(i=0; i<6; i++)
          printf("%d: %s\n", i, hstrerror(i));
}
herror指印出网络错误原因信息字符串


--------------------------------------------------------------------------------
相关函数:hstrerror
表头文件:#include <netdb.h>
函数定义:void  herror(const char *s);
函数说明:herror()用来将上一个网络函数发生错误的原因输出到标准错误stderr。参数s所指的字符串会先打印出, 后面再加上错误的原因字符串。此错误原因系依照全局变量h_errno的值来决定要输出的字符串
返回值  :无
范例:参perror()
htons将16位主机字符顺序转换成网络字符顺序


--------------------------------------------------------------------------------
相关函数:htonl, ntonl, ntohs
表头文件:#include <netinet/in.h>
函数定义:unsigned short int htons(unsigned short int hostshort)
函数说明:htons()用来将参数指定的16位hostshort转换成网络字符顺序
返回值   :返回对应的网络字符顺序
范例:参getservbyport()   connect()
htonl将32位主机字符顺序转换成网络字符顺序


--------------------------------------------------------------------------------
相关函数:htons, ntohl, ntohs
表头文件:#include <netinet/in.h>
函数定义:unsigned long int htonl(unsigned long int hostlong)
函数说明:htonl()用来将参数指定的32位hostlong转换成网络字符顺序
返回值   :返回对应的网络字符顺序
范例:参getservbyport()  connect()
inet_aton将网络地址转成网络二进制的数字


--------------------------------------------------------------------------------
相关函数:inet_addr, inet_ntoa
表头文件:#include <sys/socket.h>
               #include <netinet/in.h>
               #include <arpa/inet.h>
函数定义:int inet_aton(const char *cp, struct in_addr *inp)
函数说明:inet_aton()用来将参数cp所指的网络地址字符串转成网络所使用的二进制的数字,然后存于参数inp所指的in_addr结构中
struct in_addr
{
        unsigned long int s_addr;   //数字和点组成的字符串,如192.168.0.239
}
返回值  :成功则返回非0值 , 失败则返回0
inet_addr将网络地址转成网络二进制的数字


--------------------------------------------------------------------------------
相关函数:inet_aton, inet_ntoa
表头文件:#include <sys/socket.h>
               #include <netinet/in.h>
               #include <arpa/inet.h>
函数定义:unsigned long int inet_addr(const char *cp)
函数说明:inet_addr()用来将参数cp所指的网络地址字符串转成网络所使用的二进制的数字。网络地址字符串是以数字和点组成的字符串,如192.168.0.236
返回值  : 成功则返回对应的网络二进制的数字,失败返回-1
listen等待连接


--------------------------------------------------------------------------------
相关函数:socket, bind, accpet, connect
表头文件:#include <sys/socket.h>
函数定义:int listen(int s, int backlog)
函数说明:listen()用来等待参数s的socket连线。参数backlog指定同时能处理的最大连接要求,如果连接数目达到此上限则client端将收到ECONNREFUSED的错误(请参connect())。 listen()并未开始接受连线,只是设置socket为listen模式,真正接受client()端连线的是accept()。通常 listen()会在socket()、bind()之后调用,接着才调用accept()
附加说明:listen()只适用SOCK_STREAM或SOCK_SEQPACKET的socket类型.如果socket为AF_INET则参数backlog最大值可设到128
返回值  :成功则返回0, 失败则返回-1, 错误原因存于errno中
错误代码:EBADF              参数sockfd非合法socket处理代码
               EACCESS           权限不足
               EOPNOTSUPP    指定的socket并未支援listen模式
范例:
/*
利用socket的TCP server此程序会接收由TCP client传来的字符串并显示
TCP client范例请参connect()
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PROT                 1234   /*使用port号码*/
#define MAXSOCKFD        10     /*可同时服务的最大连线数目*/

main()
{
    int sockfd, newsockfd, is_connected[MAXSOCKFD], fd;
    struct sockaddr_in addr;
    int addr_len =sizeof(struct sockaddr_in);
   
    fd_set  readfds;
    char msg[]="Welcome to server!";
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <0)
    {
         perror("socket");
         exit(1);
    }

/*填写sockaddr_in结构*/
hzero(&addr, sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockfd, &addr, sizeof(addr)) <0)
{
    perror("connect");
    exit(1);
}

if(listen(sockfd, 3)<0)
{
    perror("listen");
    exit(1);
}


/*清除连线状态旗标*/
for(fd=0; fd<MAXSOCKFD; fd++)
     is_connected[fd]=0;

while(1)
{
           FD_ZERO(&readfds);
           FD_SET(sockfd, &readfds);
}

for(fd=0; fd<MAXSOCKFD; fd++)
{
   if(is_connected[fd]) 
         FD_SET(fd, &readfds);  
}


if(!select(MAXSOCKFD, &readfds, NULL, NULL, NULL))
        continue;

/*判断是否有新连接或新信息进来*/

for(fd=0;, fd<MAXSOCKFD; fd++)
{
    if(FD_ISSET(fd, &readfds))
    {
         if(sockfd == fd)
         {
                /*接收新连接*/
                if((newsockfd = accept(sockfd, &addr, &addr_len)) < 0 )
                        perror("accept");

                /*将欢迎字符串传给cient*/
                write(newsockfd, msg, sizeof(msg) );

                is_connected(newsockfd) = 1;
                printf("Connect from %s\n", inet_ntoa(addr.sin_addr));          
         }/*:: if(sockfd == fd)*/
         else
         {
             /*接收新信息*/
            bzero(buffer, sizeof(buffer));
          
            if(read(fd, buffer, sizeof(buffer)) <=0)
            {
                   /*连接已中断,清除连接状态标志*/
                   printf("Connection closed.\n");
                   is_connected[fd]=0;
                   close(fd);
            }
            else
            {
                   printf("%s", buffer);
            }
         }/*::else- if(sockfd == fd)*/

    }/*:: if(FD_ISSET(fd, &readfds))*/

}/*::for(fd=0;, fd<MAXSOCKFD; fd++)*/

}/*::main()*/
inet_ntoa将网络二进制的数字转成网络地址


--------------------------------------------------------------------------------
相关函数:inet_addr, inet_aton
表头文件:#include <sys/socket.h>
               #include <netinet/in.h>
               #include <arpa/inet.h>
函数定义:char *inet_ntoa(struct in_addr in)
函数说明:inet_ntoa()用来将参数in所指的网络二进制数字转成网络地址,然后将指向此网络地址字符串的指针返回
struct in_addr
{
        unsigned long int s_addr; //以点和数字组成的IP地址
}
返回值 :成功则返回字符串指针, 失败则返回NULL
范例:参connect()
ntohl将32位网络字符顺序转换成主机字符顺序


--------------------------------------------------------------------------------
相关函数:htonl, htons, ntohs
表头文件:#include <netinet/in.h>
函数定义:unsigned long int ntohl(unsigned long int netlong)
函数说明:l将32位网络字符顺序转换成主机字符顺序
返回值   :返回对应的主机字符顺序
范例      :参getservent()
ntohs将16位网络字符顺序转换成主机字符顺序


--------------------------------------------------------------------------------
相关函数:htonl, htons, ntohl
表头文件:#include <netinet/in.h>
函数定义:unsigned short int ntohs(unsigned short int netshort)
函数说明:将16位网络字符顺序转换成主机字符顺序
返回值   :返回对应的主机字符顺序
范     例 :参getservent()
recvfrom经socket接收数据


--------------------------------------------------------------------------------
相关函数:recv, recvmsg, send, sendto, socket
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int recvfrom(int s, void *buf, int len, unsigned int flags,  struct sockaddr *from, int *fromlen)
函数说明:recv()用来接收远程主机经指定的socket传来的数据,并把数据存到由参数buf指向的内存空间,参数len为可接收数据的最大长度。参数flags一般设为0, 其他参数值定义参考recv()。 参数from用来指定欲传送的网络地址,结构sockaddr请参考bind(). 参数fromlen为sockaddr的结构长度
返回值 :成功则返回接收到的字符数, 失败则返回-1, 错误原因存于errno中
错误代码:
EBADF               参数s非合法的socket处理代码
EFAULT             参数中有一指针指向无法存取的内存空间
ENOTSOCK        参数s为一文件描述词,非socket
EINTR               被信号所中断
EAGAIN             此动作会令进程阻断, 但参数s的socket为不可阻断
ENOBUFS           系统的缓冲内存不足
ENOMEM            核心内存不足
EINVAL              传给系统调用的参数不正确

范例:
/*利用socket的UDP client 此程序会连线UDP server, 并将键盘输入的字符串传送给server UDP server范例请参考sendto()*/

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT   2345   /*使用的port号码*/
#define SERVER_IP   "127.0.0.1"   /*server的IP*/

main()
{
    int s, len;
    struct sockadd_in addr;
    int addr_len = sizeof(struct sockaddr_in);
    char buffer[256];

    /*建立socket*/
   if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
   {
         perror("socket");
        exit(1);
   }

   /*填写sockaddr_in结构*/
   bzero(&addr, sizeof(addr));
   addr.sin_family = AF_INET;
   addr.sin_port   = htons(PORT);
   addr.sin_addr.s_addr=inet_addr(SERVER_IP);

   while(1)
   {
        bzero(buffer, sizeof(buffer));

        /*从标准输入设备取得字符串*/
        len = read(STDIN_FILENO, buffer, sizeof(buffer));

        /*将字符串传送给server端*/
       sendto(s, buffer, len, o, &addr, addr_len);

       /*接收server端返回的字符串*/
       len = revfrom(s, buffer, sizeof(buffer), 0, &addr, &addr_len);
      
       printf("receive : %s", buffer);

   }/*while(1)*/

}/*::main()*/
recvmsg经socket接收数据


--------------------------------------------------------------------------------
相关函数:recv, recvfrom, send, sendto, sendmsg, socket
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int recvmsg(int s, struct msgaddr *msg, unsigned int flags)
函数说明:recvmsg()用来接收远程主机经指定的socket传来的数据。
参数s为已建立好连线的socket, 如果利用UDP协议则不需经过连线操作。
参数msg指向欲连线的数据结构内容,
参数flags一般设为0,
关于结构msghdr的定义请参考sendmsg()
返回值   :成功则返回接收到的字符数,失败返回-1, 错误原因存于errno中
错误代码:参recv
范例:参recvfrom()
sendmsg经socket传送数据


--------------------------------------------------------------------------------
相关函数:send, sendto, recv, recvfrom, recvmsg, socket
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int sendmsg(int s, const struct msghdr *msg, unsigned int flags)
函数说明:本函数用来将数据由指定的socket传给对方主机。
参数s为已建立好连接的socket
如果利用UDP协议则不需要经过连接操作
参数msg指向欲连接的数据结构内容,参数flags一般默认为0, 详细参send()
结构msghdr定义如下

struct msghdr
{
    void *msg_name;                /*Address to send to /receive from */
    socklen_t  msg_namelen;     /*Length of address data*/
    struct iovec  *msg_iov;        /*Vector of data to send/recieve into */
    size_t msg_iovlen;               /*Number of elements in the vector*/
    void *msg_control;              /*Ancillary data*/
    size_t  msg_controllen;        /*Ancillary data buffer length*/
    int msg_flags;                     /*Flags on received message*/
};

返回值 : 成功则返回实际传送出去的字符数, 失败返回-1, 错误原因存于errno中
错误代码:参recv()
范例    :参sendto()
sendto经socket传送数据


--------------------------------------------------------------------------------
相关函数:send, sendmsg, recv, recvfrom, socket
表头文件:#include <sys/types.h>
               #incude <sys/socket.h>
函数定义:int sendto(int s, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen)
函数说明:本函数用来将数据由指定的socket传给对方主机。
参数s为已建立好连接的socket,如果利用UDP协议则不需经连接操作
参数msg指向欲连线的数据内容,
参数len则为数据长度
参数flags一般设为0,详细参send()
参数to用来指定欲传送的网络 地址,结构sockaddr请参bind()
参数tolen为sockaddr结构长度

返回值 :成功则返回实际传送出去的字符数, 失败返回-1, 错误原因存于errno中
错误代码:参recv()

范例:
/*
  利用socket的UDP server
  此程序会接收由UDP client传来的字符串然后再传送回client
  TCP client范例请参考 recvfrom()
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 2345   /*使用的PORT号码*/
main()
{
     int sockfd, len;
     struct sockaddr_in addr;
     int addr_len=sizeof(struct sockaddr_in);
     char buffer[256];

     /*建立socket*/
     if((sockfd = socket(AF_INET, SOCK_DGREM, 0))<0)
     {
          perror("socket");
          exit(1);
     }
    
     /*填写sockaddr_in结构*/
     bzero(&addr, sizeof(addr));
   
     addr.sin_family=AF_INET;
     addr.sin_port=htons(PORT);
     addr.sin_addr.s_addr=htonl(INADDR_ANY);
   
     if(bind(sockfd, &addr, sizeof(addr)) < 0)
     {
           perror("connect");
           exit(1);
     }

     while(1)
      {
             /*接收client端传来的字符串*/
             bzero(buffer, sizeof(buffer));
             len=recvfrom(sockfd, buffer, sizeof(buffer), 0 , &addr, &addr_len);
            
             /*显示client端的网络地址IP*/
             printf("receive from %s\n", inet_ntoa(addr.sin_addr));

             /*将字串返回给client端*/           
             sendto(sockfd, buffer, len, 0, &addr, addr_len);

      }/*::while(1)*/
    
}/*::main()*/
recv经socket接收数据


--------------------------------------------------------------------------------
相关函数:recvfrom, recvmsg, send, sendto, socket
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int recv(int s, void *buf, int len, unsigned int flags)
函数说明:recv()用来接收远端主机经指定的socket传来的数据,并把数据存到由参数buf指向的内存空间,
参数len为可接收数据的最大长度
参数flags一般设为0,其他值设置如下:
       MSG_OOB                接收以out-of-band送出的数据
       MSG_PEEK               返回来的数据并不会在系统内删除,如果再调用recv()会返回相同的数据内容
       MSG_WAITALL         强迫接受到len大小的数据后才能返回,除非有错误或信号产生
       MSG_NOSIGNAL        此操作不愿被SIGPIPE信号中断
返回值 :成功则返回接收到的字符数,失败则返回-1, 错误原因存于errno中
错误代码:
EBADF            参数s非合法的socket处理代码
EFAULT          参数中有一指针指向无法存取的内存空间
ENOTSOCK     参数s为一文件描述词,非socket
EINTR            被信号所中断
EAGAIN          此动作会令进程阻断,但参数s的socket为不可阻断
ENOBUFS        系统的缓冲内存不足
ENOMEM         核心内存不足
EINVAL           传给系统调用的参数不正确

范例    :参listen()
send经socket传送数据


--------------------------------------------------------------------------------
相关函数:sendto, sendmsg, recv, recvfrom, socket
表头文件:#include <sys/types.h>
               #inlcude <sys/socket.h>
函数定义:int send(int s, const void *msg, int len, unsigned int flags)
函数说明:本函数用来把数据由指定的socket传给对方主机。
参数s为已建立好连线的socket
参数msg指向欲连线的数据内容,参数len则为数据长度
参数flags一般设为0 ,详参recv

返回值 :成功则返回实际传送出去的字符数, 失败返回-1, 错误原因存于errno中 ,
错误代码:参recv
范例:      参connect()
setprotoent打开网络协议的数据文件


--------------------------------------------------------------------------------
相关函数:getprotobyname, getprotobynumber, endprotoent
表头文件:#include <netdb.h>
函数定义:void setprotoent(int stayopen)
函数说明:setprotoent()用来打开/etc/protocols, 如果参数stayopen值为1, 则接下来的getprotobyname()或getprotobynumber()将不会自动关闭此文件
setservent打开主机网络服务的数据文件


--------------------------------------------------------------------------------
相关函数:getservent, getservbyname, getservbyport, endservent
表头文件:#include <netdb.h>
函数定义:void setservent(int stayopen)
函数说明:本函数用来打开/etc/services如果参数stayopen值为1,则接下来的getservbyname()或getservbyport()将不会自动关闭此文件
setsockopt设置socket状态


--------------------------------------------------------------------------------
相关函数:getsockopt
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int setsockopt(int s, int level, int optna,e, const void *optval, socklen_t optlen)
函数说明:\本函数用来设置参数s指定的插座的状态。

参数level代表欲设置的网络层,一般高成SOL_SOCKET以存取socket层
参数optname代表欲设置的选项,有下列几种数据
SO_DEBUG                     打开或关闭排错模式
SO_REUSEADDR              允许在bind()过程中本地地址可重复使用
SO_TYPE                       返回socket形态(如SOCK_STREAM)
SO_ERROR                     返回socket已发生的错误原因
SO_DONTROUTE            送出的数据包不要利用路由设备来传输
SO_BROADCAST             使用广播方式传送
SO_SNDBUF                   设置送出的暂存区大小
SO_RCVBUF                   设置接收的暂存区大小
SO_KEEPALIVE               定期确定连接是否已终止
SO_OOBINLINE              当接收到OOB(out-of-band)数据时会马上送到标准输入设备
SO_LINGER                    确保数据安全且可靠的传送出去

参数optval代表欲设置的值
参数optlen则为optval的长度

附加说明:
                EBADF                   参数s并非合法的socket处理代码
                ENOTSOCK            参数s为一文件描述词,非socket
                ENOPROTOOPT      参数optname指定的选项不正确
                EFAULT                 参数optval指针指向无法存取的内存空间

范例:参getsockopt()
socket建立一个socket通信


--------------------------------------------------------------------------------
相关函数:accept, bind, connect, listen
表头文件:#include <sys/types.h>
               #include <sys/socket.h>
函数定义:int socket(int domain, int type, int protocol)
函数说明:socket()用来建立一个新的socket,也一是向系统注册,通知系统建立一通信端口。
参数domain指定使用何种的地址类型,完整的定义在/usr/include/bits/socket.h内,常见的定义如下
PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL                UNIX进程通讯协议P
PF_INET/AF_INENT                                             IPV4网络协议
PF_INET6/AF_INET6                                           IPv6网络协议
PF_IPX/AF_IPX                                                   IPX-Novell协议
PF_NETLINK/AF_NETLINK                                    核心用户接口装置
PF_X25/AF_X25                                                  ITU-T X.25/ISO-8208协议
PF_AX25/AF_AX25                                              业余无线AX.25协议
PF_ATMPVC/AF_ATMPVC                                     存取原始ATM PVCs
PF_APPLETALK/AF_APPLETALK                            Appletalk(DDP)协议
PF_PACKET/AF_PACKET                                      初级封包接口

参数type有下列几种数值:
SOCK_STREAM                       提供双向连续且可信赖的数据流,即TCP,支持OOB(out-of-band)机制。在所有数据传送前必须使用connect()来建立连线状态
SOCK_DGRAM                         使用不连续不可信赖的数据包连接
SOCK_SEQPACKET                  提供连续可信赖的数据包连接
SOCK_RAW                            提供原始网络协议存取
SOCK_RDM                             提供可信赖的数据包连接
SOCK_PACKET                        提供和网络驱动程序直接通信

返回值  :成功则返回socket处理代码, 失败则返回-1
错误代码:
  EPROTONOSUPPORT            参数domain指定的类型不支持参数type或protocol指定的协议
  ENFILE                                核心内存不足, 无法建立新的socket结构
  EMFILE                                进程文件表溢出,无法再建立新的socket
  EACCESS                             权限不足,无法建立参数type或protocol指定的协议
  ENOBUFS/ENOMEM               内存不足
  EINVAL                                参数domain/type/protocol不合法

范例:参connect()
shutdown终止socket通信
--------------------------------------------------------------------------------
相关函数:socket, connect
表头文件:#include <sys/socket.h>
函数定义:int shutdown(int s, int how)
函数说明:用来终止参数s所指定的socket连接
参数s是连接中的socket处理代码
参数how有下列几种情况:
how=0            终止读取操作
how=1            终止传送操作
how=2            终止读取及传送操作
返回值 :成功返回0, 失败返回-1, 错误原因存于errno
错误代码:
               EBADF                  参数s不是有效的socket处理代码
               ENOTSOCK            参数s为一文件描述词,非socket
               ENOTCONN            参数s指定的socket并未连接

posted @ 2011-05-19 10:39  ACE封印  Views(738)  Comments(0Edit  收藏  举报