www.linuxaid.com.cn
工程师 Dracula翻译
这些东西是我从网上拉下来的。
这“服务器/客户”的例子中使用了一些协议,可能会非常有用。
BSD套接字
套接字是4.1BSD首次引入,并且在其改进后继续在版本4.2BSD中使用至今的一种通用网络功能。套接字仍在当今的许多发布版的UNIX中使用。(在system V中传输层协议(TLI)是可选的)。套接字允许在相同或不同机器间,两个进程间进行通讯。在两台机器间的默认通信是使用网际协议(Internet proctols)。当然也可选择使用另外一些协议比如:DECnet。
在一个程序员看来,套按字非常像一个低层文件描述符。这是因为使用read()和write()对套接字操作与对文件和管道操作的方式是一样的。套接字与普通文件描述符的不同在于:在创建套接字通过一个特别的操作变量来控制套接字。这个在套接字与普通文件描述符之间的有一些区别的原因是:与一般磁盘读写相比,建立网络连接比较复杂。
在大多数套接字操作数使用中,客户与服务器必须被指定。服务器是一个为客户的需要而完成一些功能的进程。为了在以下论述的目的,在没有特殊情况下,这服务器与客户的角色是不可以互换,并且是不对称的。
套接字描述符的使用分三个阶段:
在不可靠连接或数据报模式下套接字的使用,在客户与服务器之间是在同一个host上。这种情况下,客户端不必明确建立一个同服务器的连接。当然,客户端必须知道服务器的地址。而服务器,只需要简单地等待从客户来的信息。客户端的地址是接收信息请求参数的一部分,并且被用来作为服务器答应。
在基与同一host的服务器与客户端的可靠连接中,套接字被建立和使用的情况下,服务器和客户端的概念被进一步加强了。这个模型被经常用来作为面向连接的客户/服务器模型的参考。
基与不同host的服务器与客户端的可靠连接,是上一段介绍的应用的延伸。
基与不同host的服务器与客户端的不可靠连接,在这里不予讨论。但可以从以上两段推导出。
--------------------------------------------------
使用socketpair()创建套接字
#include
#include
int socketpair(int af, int type, int protocol, int sv[2])
|
运行socketpair()的结果是创建两个连接的套接字。sv[]是一个数组,用来存放当函数返回时套接字的文件描述符。每个在sv[]中的描述符与每个通讯端相联系,都可被用来读写。这就意味着在父进程与子进程间的全双工通信是可能的。
一般情况下,其中一个描述为父进程保留,而子进程使用另一个。父进程可以关闭子进程的描述符,相反的,子进程可以关闭父进程的描述符。fork()函数仍然被用来作为传递一个套接字到子进程。
af保存了套接字属于的域或地址族。type是需要建立的套接字类型。
域指的是通信进程存在的空间,一般的域包括:
AF_UNIX:在系统与进程间通信。
AF_INET:在相间或不同系统上使用IP/UDP/TCP的进程间通信,
套接字类型指的是通信的“风格”,最常用的两种形式是:
SOCK_STREAM:没有边界记录的数据流。其在网络中的传送是被保证的;如果传送无效,则发送方收到一个错误信号。
SOCK_DGRAM:一种记录流,每次指定一个大小。在网络中的传送是不被保证的。
在"protocol"参数中置0是非常普遍的。这样允许系统选择被family和type两个参数指定的协议作为首选协议。
例子:
(borrowed from 4.3BSD IPC Tutorial by Stuart Sechrest)
#define DATA1 "test string 1"
#define DATA2 "test string 2"
#include
#include
#include
#include
main()
{
int sockets[2], child;
char buf[1024];
/* Get the socket pair */
if (socketpair(AF_UNIX, SOCK_STREAM,
0, sockets) < 0) {
printf("error %d on socketpair ", errno);
exit(1);
}
/* create child process */
if ((child = fork()) == -1) {
printf("fork error %d ", errno);
exit(1);
}
if (child != 0) { /* this is the parent */
/* close child's end of socket */
close(sockets[0]);
/* read message from child */
if (read(sockets[1], buf, sizeof(buf)) < 0) {
printf("error %d reading socket ", errno);
exit(1);
}
printf("-->%s ", buf);
/* write message to child */
if (write(sockets[1], DATA1, sizeof(DATA1)) < 0) {
printf("error %d writing socket ", errno);
exit(1);
}
/* finished */
close(sockets[1]);
} else { /* the child */
/* close parent's end of socket */
close(sockets[1]);
/* send message to parent */
if (write(sockets[0], DATA2, sizeof(DATA1)) < 0) {
printf("error %d writing socket ", errno);
exit(1);
}
/* get message from parent */
if (read(sockets[0], buf, sizeof(buf)) < 0) {
printf("error %d reading socket ", errno);
exit(1);
}
printf("-->%s ", buf);
/* finished */
close(sockets[0]);
}
}
------------------------------------------------------------
|
使用socket()创建套接字