網路編程函數
① Qt網路編程out和in函數的意思的用法
out是一個QDataStream 對象,將聲明QByteArray的實例block最為存儲緩沖區,模式為只寫。 同樣你去看代碼in是一個只讀流,將socket中的數據讀出來的功能。in>>的意思是讀出到blocksize中。和iostream很像,out和in都和網路模塊沒任何關系。
為了保證在客戶端能接收到完整的文件,都在數據流的最開始寫入完整文件的大小信息,這樣客戶端就可以根據大小信息來判斷是否接受到了完整的文件。而在 伺服器端,在發送數據時就要首先發送實際文件的大小信息,但是,文件的大小一開始是無法預知的,所以先使用了out<< (quint16) 0;在block的開始添加了一個quint16大小的空間,也就是兩位元組的空間,它用於後面放置文件的大小信息。
然後 out<<tr(「hello Tcp!!!」);輸入實際的文件,這里是字元串。當文件輸入完成後,在使用out.device()->seek(0);返回到block的開 始,加入實際的文件大小信息,也就是後面的代碼,它是實際文件的大小:out<<(quint16) (block.size() – sizeof(quint16));
② linux網路編程中socket函數詳細解釋下吧
函數原型:int socket(int family,int type,int protocol); 參數解釋:family指定協議簇,UNIX下(包括linux)有:AF_INET,AF_INET6,AF_LOCAL,AF_ROUTE,AF_KEY,分別是IPv4,IPv6協議,UNIX域協議,路由套介面,密鑰套介面; type指定套介面類型:unix下有四種,分別是:SOCK_STREAM,SOCK_DGRAM,SOCK_SEQPACKET,SOCK_RAW。(流套接字,數據報套接字,有序分組套接字,原始套接字),SOCK_SEQPACKET已很少使用; protocol:IPPROTO_TCP,IPPROTO_UDP,IPPROTO_SCTP,分別是TCP傳輸協議,UDP傳輸協議,SCTP傳輸協議; 函數返回一個非負整數值,類似於文件描述符(linux內核知識),稱之為套介面描述字,簡稱套接字。《Linux就該這么學》這本書,希望你能感受到linux系統和這本書帶給你的好處及幫助。
③ 網路編程中select函數如何接受一個accept事件
#include <winsock.h>
#include <stdio.h>
#define PORT 5150 //埠
#define MSGSIZE 1024 //信息大小
#pragma comment(lib, "ws2_32.lib")
int g_iTotalConn = 0; //連接數量
SOCKET g_CliSocketArr[FD_SETSIZE]; //套接字數組
DWORD WINAPI WorkerThread(LPVOID lpParameter);//線程函數
int main()
{
WSADATA wsaData;
SOCKET sListen, sClient;
SOCKADDR_IN local, client;
int iaddrSize = sizeof(SOCKADDR_IN);
DWORD dwThreadId;
// Initialize Windows socket library
//裝載套接字型檔
WSAStartup(0x0202, &wsaData);
// Create listening socket
//創建套接字
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind
//綁定
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// Listen
//監聽
listen(sListen, 3);
// Create worker thread
//創建線程
CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
while (TRUE)
{
// Accept a connection
//接受一個連接,返回的是客戶套的套接字
sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);
//這里client的SOCKADDR_IN client 中可以取出IP
printf("Accepted client:%s:%d ", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
// Add socket to g_CliSocketArr
//把客戶端套接字放入數組中
g_CliSocketArr[g_iTotalConn++] = sClient;
}
return 0;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)//線程
{
int i;
fd_set fdread;//結構
int ret;
struct timeval tv = {1, 0};//超時時間 SELECT模型中用到的這里是1秒
char szMessage[MSGSIZE];//信息數組,事實上就是個緩沖區
while (TRUE)
{
FD_ZERO(&fdread);//清空fd_set結構
for (i = 0; i < g_iTotalConn; i++)
{
FD_SET(g_CliSocketArr[i], &fdread);//把客戶套接字放到SELECT要求的數組中
}
//**************************************
// We only care read event
//只關心讀的情況
ret = select(0, &fdread, NULL, NULL, &tv);
if (ret == 0)
{
// Time expired 超時
continue;
}
//如果SELECT返回不是0
for (i = 0; i < g_iTotalConn; i++)
{
if (FD_ISSET(g_CliSocketArr[i], &fdread))
{
// A read event happened on g_CliSocketArr[i]
//一個可讀發生在這個套接字上
ret = recv(g_CliSocketArr[i], szMessage, MSGSIZE, 0);
//把它讀出到緩沖區
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
// Client socket closed
//客戶端關閉
printf("Client socket %d closed. ", g_CliSocketArr[i]);
closesocket(g_CliSocketArr[i]);//關閉這個套接字
if (i < g_iTotalConn - 1)
{
//將數組中最後一個套接字挪到當前的位置上
g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];
}
}
else
{
// We received a message from client
//如果以上沒發生,那麼就接收到一個客戶端的信息
szMessage[ret] = '