面向连接的协议(如TCP)的套接字系统调用:
服务器必须首先启动,直到它执行完accept()调用,进入等待状态后,方能接收客户请求。假如客户在此前
启动,则connect()将返回出错代码,连接不成功。
无连接协议的套接字调用:
无连接服务器也必须先启动,否则客户请求传不到服务进程。无连接客户不调用connect()。因此在数据发
送之前,客户与服务器之间尚未建立完全相关,但各自通过socket()和bind()建立了半相关。发送数据时,
发送方除指定本地套接字号外,还需指定接收方套接字号,从而在数据收发过程中动态地建立了全相关。
本实例使用面向连接协议的客户/服务器模式:
服务器方程序:
/* File Name: streams.c */
#include
#include
/* 这个程序建立一个套接字,然后开始无限循环;每当它通过循环接收到一个连接,则打印出一个信息。
当连接断开,或接收到终止信息,则此连接结束,程序再接收一个新的连接。命令行的格式是:streams */
main( )
{
int sock, length;
struct sockaddr_in server;
struct sockaddr tcpaddr;
int msgsock;
char buf[1024];
int rval, len;
/* 建立套接字 */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror(“opening stream socket”);
exit(1);
}
/* 使用任意端口命名套接字 */
server.sin_family = AF_INET;
server.sin_port = INADDR_ANY;
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror(“binding stream socket”);
exit(1);
}
/* 找出指定的端口号并打印出来 */ (通过getsockname来发现绑定一个套接字的地址)
length = sizeof(server);
if (getsockname(sock, (struct sockaddr *)&server, &length) < 0) {
perror(“getting socket name”);
exit(1);
}
printf(“socket port #%d/n”, ntohs(server.sin_port));
/* 开始接收连接 */
listen(sock, 5);
len = sizeof(struct sockaddr);
while(1)
{msgsock = accept(sock, (struct sockaddr *)&tcpaddr, (int *)&len); (会阻塞,但此时已经看出服务器的端口)
if (msgsock == -1)
perror(“accept”);
memset(buf, 0, sizeof(buf));
if ((rval = recv(msgsock, buf, 1024)) < 0)
perror(“reading stream message”);
if (rval == 0)
printf(“ending connection /n”);
else
printf(“-->;%s/n”, buf);
closesocket(msgsock);
}
/* 因为这个程序已经有了一个无限循环,所以套接字“sock”从来不显式关闭。然而,当进程被杀死或正
常终止时,所有套接字都将自动地被关闭。*/
exit(0);
}