以下两个示例说明启动和接受 Internet 系列流连接。

以下是针对服务器的示例程序。服务器创建套接字并将名称绑定到此套接字,然后显示端口号。此程序调用 listen(3SOCKET) 将套接字标记为可以接受连接请求并初始化请求队列。此程序的其余部分为一个死循环。每次循环都接受一个新的连接并将其从队列中删除,从而创建一个新的套接字。服务器读取并显示此套接字中的消息,然后关闭此套接字。地址绑定中介绍了 in6addr_any 用法。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define TRUE 1
/*
* This program creates a socket and then begins an infinite loop.
* Each time through the loop it accepts a connection and prints
* data from it. When the connection breaks, or the client closes
* the connection, the program accepts a new connection.
*/
main() {
int sock, length;
struct sockaddr_in6 server;
int msgsock;
char buf[1024];
int rval;
/* Create socket. */
sock = socket(AF_INET6, SOCK_STREAM, 0);
if (sock == -1) {
perror("opening stream socket");
exit(1);
}
/* Bind socket using wildcards.*/
bzero (&server, sizeof(server));
server.sin6_family = AF_INET6;
server.sin6_addr = in6addr_any;
server.sin6_port = 0;
if (bind(sock, (struct sockaddr *) &server, sizeof server)
== -1) {
perror("binding stream socket");
exit(1);
}
/* Find out assigned port number and print it out. */
length = sizeof server;
if (getsockname(sock,(struct sockaddr *) &server, &length)
== -1) {
perror("getting socket name");
exit(1);
}
printf("Socket port #%d\n", ntohs(server.sin6_port));
/* Start accepting connections. */
listen(sock, 5);
do {
msgsock = accept(sock,(struct sockaddr *) 0,(int *) 0);
if (msgsock == -1)
perror("accept");
else do {
memset(buf, 0, sizeof buf);
if ((rval = read(msgsock,buf, sizeof(buf))) == -1)
perror("reading stream message");
if (rval == 0)
printf("Ending connection\n");
else
/* assumes the data is printable */
printf("-->%s\n", buf);
} while (rval > 0);
close(msgsock);
} while(TRUE);
/*
* Since this program has an infinite loop, the socket "sock" is
* never explicitly closed. However, all sockets are closed
* automatically when a process is killed or terminates normally.
*/
exit(0);
}
要启动连接,示例 7–2 中的客户机程序会创建一个流套接字,然后调用 connect(3SOCKET),指定用于连接的套接字地址。如果存在目标套接字,并且接受了请求,则连接会完成。现在,程序可以发送数据。数据按顺序传送,并且没有消息边界。此连接会在任何一个套接字关闭时销毁。有关此程序中的数据表示例程(如 ntohl(3SOCKET)、ntohs(3SOCKET)、htons(3SOCKET) 以及 htonl(3XNET))的更多信息,请参见 byteorder(3SOCKET) 手册页。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define DATA "Half a league, half a league . . ."
/*
* This program creates a socket and initiates a connection with
* the socket given in the command line. Some data are sent over the
* connection and then the socket is closed, ending the connection.
* The form of the command line is: streamwrite hostname portnumber
* Usage: pgm host port
*/
main(int argc, char *argv[])
{
int sock, errnum, h_addr_index;
struct sockaddr_in6 server;
struct hostent *hp;
char buf[1024];
/* Create socket. */
sock = socket( AF_INET6, SOCK_STREAM, 0);
if (sock == -1) {
perror("opening stream socket");
exit(1);
}
/* Connect socket using name specified by command line. */
bzero (&server, sizeof (server));
server.sin6_family = AF_INET6;
hp = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT, &errnum);
/*
* getipnodebyname returns a structure including the network address
* of the specified host.
*/
if (hp == (struct hostent *) 0) {
fprintf(stderr, "%s: unknown host\n", argv[1]);
exit(2);
}
h_addr_index = 0;
while (hp->h_addr_list[h_addr_index] != NULL) {
bcopy(hp->h_addr_list[h_addr_index], &server.sin6_addr,
hp->h_length);
server.sin6_port = htons(atoi(argv[2]));
if (connect(sock, (struct sockaddr *) &server,
sizeof (server)) == -1) {
if (hp->h_addr_list[++h_addr_index] != NULL) {
/* Try next address */
continue;
}
perror("connecting stream socket");
freehostent(hp);
exit(1);
}
break;
}
freehostent(hp);
if (write( sock, DATA, sizeof DATA) == -1)
perror("writing on stream socket");
close(sock);
freehostent (hp);
exit(0);
}
可以将一对一 SCTP 连接支持添加到流套接字。以下示例代码将 -p 添加到现有程序,使此程序可以指定要使用的协议。
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
struct protoent *proto = NULL;
int c;
int s;
int protocol;
while ((c = getopt(argc, argv, "p:")) != -1) {
switch (c) {
case 'p':
proto = getprotobyname(optarg);
if (proto == NULL) {
fprintf(stderr, "Unknown protocol: %s\n",
optarg);
return (-1);
}
break;
default:
fprintf(stderr, "Unknown option: %c\n", c);
return (-1);
}
}
/* Use the default protocol, which is TCP, if not specified. */
if (proto == NULL)
protocol = 0;
else
protocol = proto->p_proto;
/* Create a IPv6 SOCK_STREAM socket of the protocol. */
if ((s = socket(AF_INET6, SOCK_STREAM, protocol)) == -1) {
fprintf(stderr, "Cannot create SOCK_STREAM socket of type %s: "
"%s\n", proto != NULL ? proto->p_name : "tcp",
strerror(errno));
return (-1);
}
printf("Success\n");
return (0);
}