JavaScript is required to for searching.
跳过导航链接
退出打印视图
编程接口指南     Oracle Solaris 10 1/13 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

1.  内存和 CPU 管理

2.  用于 Solaris Cluster 的远程共享内存 API

3.  会话描述协议 API

4.  进程调度程序

5.  地址组 API

6.  输入/输出接口

7.  进程间通信

8.  套接字接口

SunOS 4 二进制兼容性

套接字概述

套接字库

套接字类型

接口组

套接字基础知识

创建套接字

绑定本地名称

建立连接

连接错误

数据传输

关闭套接字

连接流套接字

输入/输出多路复用

数据报套接字

标准例程

主机和服务名称

主机名-hostent

网络名称-netent

协议名-protoent

服务名-servent

其他例程

客户机/服务器程序

套接字和服务器

套接字和客户机

无连接服务器

高级套接字主题

带外数据

非阻塞套接字

异步套接字 I/O

中断驱动套接字 I/O

信号和进程组 ID

选择特定的协议

地址绑定

套接字选项

inetd 守护进程

广播及确定网络配置

使用多播

发送 IPv4 多播数据报

接收 IPv4 多播数据报

发送 IPv6 多播数据报

接收 IPv6 多播数据报

流控制传输协议

SCTP 栈实现

SCTP 套接字接口

sctp_bindx()

sctp_opt_info()

sctp_recvmsg()

sctp_sendmsg()

sctp_send()

分叉关联

sctp_getpaddrs()

sctp_freepaddrs()

sctp_getladdrs()

sctp_freeladdrs()

SCTP 用法代码示例

9.  使用 XTI 和 TLI 编程

10.  包过滤钩子

11.  传输选择和名称到地址映射

12.  实时编程和管理

13.  Solaris ABI 和 ABI 工具

A.  UNIX 域套接字

索引

数据报套接字

数据报套接字提供了对称数据交换接口,无需建立连接。每条消息都带有目标地址。下图显示了服务器与客户机之间的通信流。

服务器的 bind(3SOCKET) 步骤为可选步骤。

图 8-2 使用数据报套接字的无连接通信

image:此图使用 sendto 和 recvfrom 函数说明服务器和客户机之间的数据流。

按照创建套接字中所述创建数据报套接字。如果需要特定本地地址,必须在首次数据传输之前执行 bind(3SOCKET) 操作。否则,系统会在首次发送数据时设置本地地址或端口。使用 sendto(3SOCKET) 发送数据。

sendto(s, buf, buflen, flags, (struct sockaddr *) &to, tolen);

sbuf buflenflags 参数与面向连接的套接字中的相应参数相同。to tolen 值指示消息预期接受者的地址。在本地检测到的错误情况(如无法访问网络)会导致返回 -1,并将 errno 设置为错误号。

recvfrom(s, buf, buflen, flags, (struct sockaddr *) &from, &fromlen);

要在数据报套接字上接收消息,请使用 recvfrom(3SOCKET)。在调用之前,fromlen 将会设置为 from 缓冲区的大小。返回时, fromlen 将会设置为接收数据报的地址的大小。

数据报套接字还可以使用 connect(3SOCKET) 调用将套接字与特定目标地址关联。然后,此套接字便可以使用 send(3SOCKET) 调用。如果在未显式指定目标地址的套接字上发送数据,则目标地址为已连接的对等方。只传送从该对等方接收的数据。一个套接字一次只能有一个已连接的地址。再次调用 connect(3SOCKET) 会更改目标地址。将立即返回数据报套接字上的连接请求。系统将记录对等方的地址。不能将 accept(3SOCKET)listen(3SOCKET) 用于数据报套接字。

连接数据报套接字之后,便可以从先前的 send(3SOCKET) 调用中异步返回错误。此套接字可以在后续套接字操作中报告这些错误。或者,此套接字可以使用 getsockopt(3SOCKET) 的选项 SO_ERROR 来询问错误状态。

以下示例代码说明如何通过创建一个套接字、将名称绑定到该套接字以及将消息发送到该套接字来发送 Internet 调用。

示例 8-5 发送 Internet 系列数据报

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define DATA "The sea is calm, the tide is full . . ."   
/*
 * Here I send a datagram to a receiver whose name I get from
 * the command line arguments. The form of the command line is:
 * dgramsend hostname portnumber
 */
main(int argc, char *argv[])
{
    int sock, errnum;
    struct sockaddr_in6 name;
    struct hostent *hp;
    /* Create socket on which to send. */
    sock = socket(AF_INET6,SOCK_DGRAM, 0);
    if (sock == -1) {
        perror("opening datagram socket");
        exit(1);
    }
    /*
     * Construct name, with no wildcards, of the socket to ``send''
     * to. getinodebyname returns a structure including the network
     * address of the specified host. The port number is taken from
     * the command line.
     */
    hp = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT, &errnum);
    if (hp == (struct hostent *) 0) {
        fprintf(stderr, "%s: unknown host\n", argv[1]);
        exit(2);
    }
    bzero (&name, sizeof (name));
    memcpy((char *) &name.sin6_addr, (char *) hp->h_addr,
       hp->h_length);
    name.sin6_family = AF_INET6;
    name.sin6_port = htons(atoi(argv[2]));
    /* Send message. */
    if (sendto(sock,DATA, sizeof DATA ,0,
        (struct sockaddr *) &name,sizeof name) == -1)
        perror("sending datagram message");
    close(sock);
    exit(0);
}

以下样例代码说明如何通过创建套接字,将名称绑定到套接字,然后从套接字进行读取来读取 Internet 调用。

示例 8-6 读取 Internet 系列数据报

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
/*
 * This program creates a datagram socket, binds a name to it, then
 * reads from the socket.
 */
 main()
{
    int sock, length;
    struct sockaddr_in6 name;
    char buf[1024];
    /* Create socket from which to read. */
    sock = socket(AF_INET6, SOCK_DGRAM, 0);
    if (sock == -1) {
        perror("opening datagram socket");
        exit(1);
    }
    /* Create name with wildcards. */
    bzero (&name, sizeof (name));
    name.sin6_family = AF_INET6;
    name.sin6_addr = in6addr_any;
    name.sin6_port = 0;
    if (bind (sock, (struct sockaddr *)&name, sizeof (name)) == -1) {
        perror("binding datagram socket");
        exit(1);
    }
    /* Find assigned port value and print it out. */
    length = sizeof(name);
    if (getsockname(sock,(struct sockaddr *) &name, &length)
            == -1) {
        perror("getting socket name");
        exit(1);
    }
    printf("Socket port #%d\n", ntohs(name.sin6_port));
    /* Read from the socket. */
    if (read(sock, buf, 1024) == -1 )
        perror("receiving datagram packet");
    /* Assumes the data is printable */
    printf("-->%s\n", buf);
    close(sock);
    exit(0);
}