网络编程函数
① 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] = '