socket編程原理(五)

務器,其系統調用時序圖如下。
面向連接的協議(如TCP)的套接字系統調用如圖2.1所示:
服務器必須首先啓動,直到它執行完accept()調用,進入等待狀態後,方能接收客戶請求。假如客戶在此前啓動,則connect()將返回出錯代碼,連接不成功。

圖2.1 面向連接的套接字系統調用時序圖:


無連接協議的套接字調用如圖2.2所示:

圖2.2 無連接協議的套接字調用時序圖
無連接服務器也必須先啓動,否則客戶請求傳不到服務進程。無連接客戶不調用connect()。因此在數據發送之前,客戶與服務器之間尚未建立完全相關,但各自通過socket()和bind()建立了半相關。發送數據時,發送方除指定本地套接字號外,還需指定接收方套接字號,從而在數據收發過程中動態地建立了全相關。
實例
本實例使用面向連接協議的客戶/服務器模式,其流程如圖2.3所示:

圖2.3 面向連接的應用程序流程圖
服務器方程序:
/* File Name: streams.c */
#include 
#include 
#define TRUE 1
/* 這個程序建立一個套接字,然後開始無限循環;每當它通過循環接收到一個連接,則打印出一個信息。當連接斷開,或接收到終止信息,則此連接結束,程序再接收一個新的連接。命令行的格式是: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);
}
/* 找出指定的端口號並打印出來 */
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);
do {
msgsock = accept(sock, (struct sockaddr *)&tcpaddr, (int *)&len);
if (msgsock == -1)
perror("accept");
else do{
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);
}while (rval != 0);
closesocket(msgsock);
} while (TRUE);
/* 因爲這個程序已經有了一個無限循環,所以套接字"sock"從來不顯式關閉。然而,當進程被殺死或正常終止時,所有套接字都將自動地被關閉。*/
exit(0);
}
客戶方程序:
/* File Name: streamc.c */
#include 
#include 
#define DATA "half a league, half a league ..."
/* 這個程序建立套接字,然後與命令行給出的套接字連接;連接結束時,在連接上發送
一個消息,然後關閉套接字。命令行的格式是:streamc 主機名 端口號 
端口號要與服務器程序的端口號相同 */
main(argc, argv)
int argc;
char *argv[ ];
{
int sock;
struct sockaddr_in server;
struct hostent *hp, *gethostbyname( );
char buf[1024];
/* 建立套接字 */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
/* 使用命令行中指定的名字連接套接字 */
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if (hp == 0) {
fprintf(stderr, "%s: unknown host /n", argv[1]);
exit(2); 
}
memcpy((char*)&server.sin_addr, (char*)hp->h_addr, hp->h_length);
sever.sin_port = htons(atoi(argv[2]));
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
perror("connecting stream socket");
exit(3);
}
if (send(sock, DATA, sizeof(DATA)) < 0)
perror("sending on stream socket"

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章