作者:龍飛
現在,我們通過accept()創建了新的socket,也就是我們類中的數據成員communicationSock,現在,我們就可以通過這個socket進行通訊了。
TCP通訊模型
在介紹函數之前,我們應該了解一些事實。TCP的Server/Client模型類似這樣:
ServApp——ServSock——Internet——ClntSock——ClntApp
當然,我們這里的socket指的就是用于“通訊”的socket。TCP的server端至少有兩個socket,一個用于監聽,一個用于通訊;TCP的server端可以只有一個socket,這個socket同時“插”在server的兩個socket上。當然,插上listen socket的目的只是為了創建communication socket,創建完備后,listen是可以關閉的。但是,如果這樣,其他的client就無法再連接上server了。
我們這個模型,是client的socket插在server的communication socket上的示意。這兩個socket,都擁有完整的本地地址信息以及遠程計算機地址信息,所以,這兩個socket以及之間的網絡實際上形成了一條形式上“封閉”的管道。數據包只要從一端進來,就能知道出去的目的地,反之亦然。這正是TCP協議,數據流形式抽象化以及實現。因為不再需要指明“出處”和“去向”,對這樣的socket(實際上是S/C上的socket對)的操作,就如同對本地文件描述符的操作一樣。但是,盡管我們可以使用read()和write(),但是,為了完美的控制,我們最好使用recv()和send()。
recv()和send()
int send(int socket, const void* msg, unsigned int msgLength, int flags);
int recv(int socket, void* rcvBuffer, unsigned int bufferLength, int flags);
在Linux中的實現為:
#include <sys/socket.h>
/* Send N bytes of BUF to socket FD. Returns the number sent or -1.
This function is a cancellation point and therefore not marked with
__THROW. */
extern ssize_t send (int __fd, __const void *__buf, size_t __n, int __flags);
/* Read N bytes into BUF from socket FD.
Returns the number read or -1 for errors.
This function is a cancellation point and therefore not marked with
__THROW. */
extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);
這兩個函數的第一個參數是用于“通訊”的socket,第二個參數是發送或者接收數據的起始點指針,第三個參數是數據長度,第四個參數是控制符號(默認屬性設置為0就可以了)。失敗時候傳回-1,否則傳回實際發送或者接收數據的大小,返回0往往意味著連接斷開了。
處理echo行為
void TcpServer::handleEcho()
{
const int BUFFERSIZE = 32;
char buffer[BUFFERSIZE];
int recvMsgSize;
bool goon = true;
while ( goon == true ) {
if ( (recvMsgSize = recv(communicationSock, buffer, BUFFERSIZE, 0)) < 0 ) {
throw "recv() failed";
} else if ( recvMsgSize == 0 ) {
goon = false;
} else {
if ( send(communicationSock, buffer, recvMsgSize, 0) != recvMsgSize ) {
throw "send() failed";
}
}
}
close(communicationSock);
}
本小節最后要講的函數是close(),它包含在<unistd.h>中
#include <unistd.h>
/* Close the file descriptor FD.
This function is a cancellation point and therefore not marked with
__THROW. */
extern int close (int __fd);
這個函數用于關閉一個文件描述符,自然,也就可以用于關閉socket。
下一小節是完整的源代碼。默認的監聽端口是5000。我們可以通過
$telnet 127.0.0.1 5000
驗證在本機運行的echo server程序。
posted on 2008-07-16 12:26
lf426 閱讀(8135)
評論(2) 編輯 收藏 引用 所屬分類:
SDL入門教程 、
Linux與C++ 、
socket 編程入門教程