您的位置:首页 > 理论基础 > 计算机网络

TCP/UDP网络编程

2016-03-16 16:21 555 查看
TCP/UDP网络编程
sf2gis@163.com
2012年2月07日
 

1  概述

1.1 IP,Port与Protocol

IP:网络上每个主机的唯一标识号

Port:用于标识系统中每个应用的标识号;IPV4:32位,4个字节组成;

IP与Port组合在一起可以确定一个唯一的应用;

协议:是用来规定通信双方的数据规则的.

1.2 ISO/OSI七层模型:

应用层->表示层->会话层->传输层->网络层->数据链路层->物理层

对等通信:虚拟通信,下层对上层单向提供服务;

封装:按照特定的协议将数据加入协议头(有的包含协定尾)的数据打包过程称为封装;

PDU:protocol data unit,协议数据单元,指的是对等层之间交换的数据包.

1.3 TCP/IP模型:

应用层->传输层->网络层->网络接口层

TCP提出了协议端口(protocolport,简称端口):为了标识通信实体中进行通信的进程(应用),指定一个数字作为标识,从而使两个通信进程之间交换数据,称之为端口;

后门:强制控制计算机打开某个端口进行通信,就是后门程序,也就是木马;

0~1024:系统预定义端口;(http:80,telnet:23,ftp:21,SMTP:25,pop3:110)

1025~49151:用于软件注册的端口;

49151~65535:用于动态/私有端口(易为木马等使用);

1.4 socket:

socket:最初由berkeley大学发布的一种用于应用程序调用通信协议的对象;它将通信协议中使用的共有特性进行封装以进行方便通信过程.

windows socket只支持网际域的通信区域;

1.5 网络字节顺序:

不同的计算机对字节的存储顺序可能有所不同,起始地址有的以高位存储,有的以低位存储;网络传输时,规定了固定的存储方式,因此在使用网络传输时,应使用htos(),htol()方法将本地存储内容转换为网络存储格式;

1.6 WindowsSocket:

从Berkeley Socket发展而来,以DLL形式提供;以WSAStartup()加载(windows socket api);在winXp中为ws2_32.dll,ws2_32.lib,Winsock2.h

V1.1与Unix Berkeley Socket通用性强,易移植;

有三种类型的SOCKET:

SOCK_STREAM:TCP;

SOCK_DGRAM:UDP:

SOCK_RAW:原始SOCKET;

1.7 TCP/UDP

TCP:而向连接的,有数据重发和数据校验功能;实现性弱,数据完整性高;

UDP:无连接的,实时性强,不能保证数据的完整性;

1.8 服务器与客户端差别

服务器端需要将服务器的地址端口信息绑定到指定的Socket上,此Socket监听指定IP的指定Port.TCP会在有连接请求时,建立连接,并将连接地址生成一个新的Socket.在此Socket上,进行面向连接的数据收发.UDP是无连接的,可以直接进行数据收发.

客户端只需指定服务器地址,并将此地址连接到本地Socket上,就可以进行数据收发.

2 TCP编程

2.1 TCP服务器端编程

2.1.1 加载Windows Socket DLL

使用WSAStartup(wVersionRequest,&wsaData);加载指定的WSDLL;

wVersionRequest:要求的库版本号(高位为副版本号,低位为主版本号);

wsaData:加载的库信息;

成功后返回0,否则返回错误码;

使用WSAStartup()成功加载后,应用WSACleanup()进行资源释放;

 

    //加载Socket DLL
    WORDwVersionRequest;
    WSADatawsaData;
    int err;
    wVersionRequest=MAKEWORD(1,1);//生成(高位,低位)WORD
    err=WSAStartup(wVersionRequest,&wsaData);
    if(err!=0)//如果成功调用,则返回
    {
       return;
    }
    if(LOBYTE(wsaData.wVersion)!=1||LOBYTE(wsaData.wVersion)!=1)//高位代表副版本,低位代表主版本
    {
       WSACleanup();//如果WSAStartup()成功调用DLL后,则应使用WSACleanup()释放资源
       return;
    }

2.1.2 创建 SOCKET

使用socket()函数进行创建;成功返回socket,错误返回INVALID_SOCKET;使用WSAGetLastError()获取错误码;

 

    //创建SOCKET
    SOCKETsockSrv=socket(AF_INET,SOCK_STREAM,0);//推荐指定协议类型为,则根据地址格式和Socket类型自动判断
    if(sockSrv==INVALID_SOCKET)
    {
       if(WSAEMFILE==WSAGetLastError());//返回错误码,可以据此判断错误类型
       {
           printf("No more socket descriptors are available\n");
       }
       return;
    }

2.1.3 绑定SOCKET

    //绑定SOCKET
    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(6000);
    bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
    printf("bind...\n");

2.1.4 监听SOCKET

    //监听
    listen(sockSrv,5);
    printf("listen...\n");

2.1.5 循环等待用户请求;

    SOCKADDR_IN addrClient;
    intlen=sizeof(SOCKADDR);
    while(1)
    {

}

2.1.6 接受连接请求,并返回连接SOCKET

       //接受连接请求
       SOCKETsockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);

2.1.7 以连接SOCKET进行数据收(recv)发(send)

       //发送(可以根据从客户端接收的数据进行处理,然后返回结果)
       charsendBuf[100];
       sprintf(sendBuf,"SendBuf %s is here.",inet_ntoa(addrClient.sin_addr));
       send(sockConn,sendBuf,strlen(sendBuf)+1,0);
      
       //接收(可以持续接收客户端发送的数据)
       while(1)
       {
           charreceiveBuf[100];
           recv(sockConn,receiveBuf,100,0);
           printf("%s\n",receiveBuf);
       }

2.1.8 关闭连接SOCKET,重新等待连接请求

       //关闭
       closesocket(sockConn);

2.1.9 关闭监听SOCKET;

    //非无限循环的情况下,应该关闭SOCKET,释放DLL
    closesocket(sockSrv);

2.1.10 释放Windows Socket DLL

    WSACleanup();
 

2.2 TCP客户端编程

2.2.1 加载Windows Socket DLL

WORD wVersionRequest;

WSAData wsaData;

wVersionRequset=MAKEWORD(1,1);

int err=WSAStartup(wVersionRequest,&wsaData);

if(err!=0)

{

return;

}

if(LOBYTE(wVersionRequest)!=1||HIBYTE(wVersionRequest)!=1)

{

WSACleanup();

return;

}

2.2.2 创建SOCKET

SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);

2.2.3 连接服务器SOCKET

SOCKADDR_IN addrSrv;

addrSrv.sin_family=AF_INET;

addSrv.sin_port=htons(6000);

addSrv.sin_addr.S_un.S_addr=inet_addr(“192.186.1.161”);

connect(sockClient,(SOCKADDR*)(&addrSrv ),sizeof(addrSrv));

2.2.4 收发数据

char* sendBuf=”send buf.”;

send(sockClient,sendBuf,strlen(sendBuf)+1,0);

char recvBuf=[100];

recv(sockClient,recvBuf,100,0);

2.2.5 关闭SOCKET

closesocket(sockClient);

2.2.6 释放Windows Socket DLL

WSACleanup();

 

3 UDP编程

3.1 UPD服务器端编程

3.1.1 加载Windows Socket DLL

WORD wVersionRequest;

WSAData wsaData;

int err;

wVersionRequest=MAKEWORD(1,1);

err=WSAStartup(wVersionRequest,&wsaData);

if(err!=0)

{

    return;

}

if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1)

{

WSACleanup();

    return;

}

3.1.2 创建SOCKET

SOCKET sockSrv= socket(AF_INET,SOCK_DGRAM,0);

if(sockSrv ==INVALID_SOCKET)

{

return;

}

3.1.3 绑定SOCKET

SOCKADDR_IN addrSrv;

addrSrv.sin_family=AF_INET;

addrSrv.sin_addr.S_un.S_addr=htonl(ADDR_ANY);

addrSrv.sin_port=htons(6000);

bind(sockSrv,(SOCKADDR*)(&addrSrv),sizeof(SOCKADDR));

3.1.4 收发数据

char recvBuf[100];

int len=sizeof(SOCKADDR);

SOCKADDR_IN addrClient;

recvfrom(sockSrv,recvBuf,100,0,(SOCKETADDR*)(*addrClient),&len);

 

char* sendBuf=”this is from server.”;

sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKETADDR*)(&addrClient),len);

3.1.5 关闭SOCKET

closesocket(sockSrv);

3.1.6 释放Windows Socket DLL

WSACleanup();

3.2 UPD客户端编程

3.2.1 加载Windows Socket DLL

WORD wVersionRequest;

WSAData wsaData;

int err;

wVersionRequest=MAKEWORD(1,1);

err=WSAStartup(wVersionRequest,&wsaData);

if(err!=0)

{

    return;

}

if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1)

{

WSACleanup();

    return;

}

3.2.2 创建SOCKET

SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0);

if(sockClient ==INVALID_SOCKET)

{

return;

}

 

3.2.3 收发数据

SOCKADDR_IN addrSrv;

addrSrv.sin_family=AF_INET;

addSrv.sin_port=htons(6000);

addSrv.sin_addr.S_un.S_addr=inet_addr(“192.168.1.161”);

int len=sizeof(SOCKADDR);

char* sendBuf=”this is from client.”;

sendto(sockClient,sendBuf,sizeof(sendBuf)+1,0,(SOCKADDR*)(&addrSrv),len);

char recvBuf[100];

recvfrom(sockClient,recvBuf,100,0,(SOCKADDR*)(&addrSrv),&len);

3.2.4 关闭SOCKET

closesocket(sockClient);

3.2.5 释放Windows Socket DLL

WSACleanup();

 

4 Qt网络编程

Qt网络编程使用的是Qt的网络模块(QtNetworkModule),在该模块中,各种网络编程协议都进行了相应的封装,更加方便使用.

FTP:QFtp;

Http:QNetworkAccessManager,QtNetworkReply;(QHttp类的替代);

本机信息:QHostInfo;

TCP:QTcpServer,QTcpSocket;

UDP:QUdpSocket;

代理:QNetworkProxy;

加密:QSslSocket;

使用时要添加Network模块,并包含QtNetwork模块;

4.1 HTTP

4.1.1 HTTP网络编程相关类:

QNetworkAccessManager:控制HTTP连接的关键类;一般一个程序中使用一个就可满足;用于发出请求,获得响应;

QNetworkReply:HttpReply的具体类实现,作为请求的响应,由QNetworkAccessManager返回;以串行化形式返回获得的数据;如果获得数据,就会发出readyRead()信号和downloadProgress()信号(可以不准);如果数据接收完成,就会发出finished()信号;

QNetworkRequest:HttpRequest的具体类实现;作为请求,由QNetworkAccessManager发出;

4.1.2 HTTP步骤:

4.1.2.1  创建QNetworkAccessManager类对象:

QNetworkAccessMangager*m_pHttpManager=new QNetworkAccessManager;

4.1.2.2  创建QNetworkRequest对象:

QUrl url(“urlhost”);

QNetworkReqest request(url);

4.1.2.3  创建QNetworkReply类对象:

QNetworkReply*m_pRelpy=m_pHttpManger->get(request);

4.1.2.4  连接读数据信号与槽函数:

connect(m_pReply,SIGNAL(readyRead()),this,SLOT(readReadyHttpReply ()));

4.1.2.5  连接数据读取完成信号与槽函数:

connect(m_pReply,SIGNAL(finished()),this,SLOT(finishHttpReply ()));

4.2 TCP

 

4.3 FTP

4.3.1 FTP类:QFtp

 

 

4.4 UPD服务器端编程

4.4.1 加载Windows Socket DLL

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息