TCP UDP.docx

上传人:b****3 文档编号:4470231 上传时间:2022-12-01 格式:DOCX 页数:18 大小:22.51KB
下载 相关 举报
TCP UDP.docx_第1页
第1页 / 共18页
TCP UDP.docx_第2页
第2页 / 共18页
TCP UDP.docx_第3页
第3页 / 共18页
TCP UDP.docx_第4页
第4页 / 共18页
TCP UDP.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

TCP UDP.docx

《TCP UDP.docx》由会员分享,可在线阅读,更多相关《TCP UDP.docx(18页珍藏版)》请在冰豆网上搜索。

TCP UDP.docx

TCPUDP

基于TCP和UDP的Socket编程

在OSI的各层所使用的协议:

1.应用层:

telnet,FTP,HTTP,DNS,SMTP,POP32.传输层:

TCP,UDPTCP:

面向连接的可靠的传输协议,通信前建立三次握手,握手成功后才能通信,对数据准确性要求较高的场合使用,如从网上载的安装文件,不能缺少任何信息UDP:

是无连接的

在OSI的各层所使用的协议:

1.应用层:

telnet,FTP,HTTP,DNS,SMTP,POP3

2.传输层:

TCP,UDP

TCP:

面向连接的可靠的传输协议,通信前建立三次握手,握手成功后才能通信,对数据准确性要求较高的场合使用,如从网上载的安装文件,不能缺少任何信息

UDP:

是无连接的,不可靠的传输协议,不需要建立连接,也没有重传和确认的机制,在实时性要求较高,但对数据准确度要求不是很高的场合使用,如视频会议,在线观看电影,当中丢失个别数据包并不影响整体的效果。

3.网络层:

IP

因为OSI七层结构较为复杂,所以使用较多的是TCP/IP模型,现在TCP/IP已经成为Internet上通用的工业标准

TCP/IP模型包括4个层次:

应用层,传输层,网络层,网络接口

端口:

1.为了标识通信实体中进行通信的进程(应用程序),TCP/IP协议提出了协议端口的概念

2.端口是一种抽象的软件结构(包括一些数据结构和I/O缓冲区)。

应用程序通过系统调用和某端口建立连接(binding)后,传输层传给该端口的数据都被相应的进程所接收,相应进程发给传输层的数据都通过该端口输出

3.端口用一个整数型标识符来表示,即端口号。

端口号跟协议相关,TCP/IP传输层的两个协议TCP和UDP是完全独立的的两个软件模块,因此各自的端口号也相互独立

4.端口使用一个16位的数字来表示,它的范围是0~65535,1024以下的端口号保留给预定义的服务,例如,http使用80端口

套接字(Socket)

1.Socket的出现,使得程序员可以很方便的访问TCP/IP,从而开发各种网络应用的程序

2.套接字存在于通信区域中,通信区域也叫地址族,他是一个抽象的概念,主要用于通过套接字通信的进程的共有特性综合在一起。

套接字通常只与同一个区域的套接字交换数据。

套接字的类型

1.流式套接字(SOCK_STREAM)

提供面向连接的,可靠的数据传输服务,数据无差错,无重复的发送,且按发送的顺序接收,基于TCP协议

2.数据保式套接字(SOCK_DGRAM)

提供无连接的服务,数据包以独立包形式发送,不提供无错误的保证,数据可能丢失或重复,且接收顺序混乱,基于UDP协议

基于TCP(面向连接)的Socket编程

服务器端顺序:

1.加载套接字库

2.创建套接字(socket)

3.将套接字绑定到一个本地地址和端口上(bind)

4.将套接字设为监听模式,准备接收客户请求(listen)

5.等待客户请求的到来;当请求带来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)

6.用返回的套接字和客户端进行通信(send/recv)

7.返回,等待另一个客户请求

8.关闭套接字(closesocket)

客户端程序:

1.加载套接字库

2.创建套接字(socket)

3.向服务器发送连接请求(connect)

4.和服务器端进行通信(send/receive)

5.关闭套接字(closesocket)

基于UDP(面向无连接)的socket编程

服务器端(接收端)程序:

1.加载套接字库

2.创建套接字(socket)

3.将套接字绑定到一个本地地址和端口上(bind)

4.等待接收数据(recvfrom)

5.关闭套接字(closesocket)

客户端(发送端)程序

1.加载套接字库

2.创建套接字(socket)

3.向服务器发送数据(sendto)

4.关闭套接字(closesocket)

创建基于TCP协议的CS程序的Server端所涉及的相关函数说明(按使用的先后顺序排列):

1.intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData):

作用是加载套接字库和进行套接字库的版本协商

a.参数wVersionRequested:

用于指定准备加载的Winsock库的版本,高位字节指定所需要的Winsock库的副版本,低位字节则是主版本,可用MAKEWORD(X,Y)(其中,x为高位字节,y为低位字节)方便获得wVersionRequested的正确值。

b.参数lpWSAData:

指向WSADATA结构的指针,WSAStartup用其加载的库版本有关的信息填在这个结构中

2.SOCKETsocket(intaf,inttype,intprotocol):

a.参数af指定地址族,对于TCP/IP协议的套接字,它只能是AF_INET(也可写成PF_INET)。

b.参数type指定Socket类型,对于1.1版本的Socket,它只支持两种类型的套接字,SOCK_STREAM指定产生流式套接字,y产生数据报套接字。

c.参数protocol与特定的地址家族相关的协议,如果指定为0,那么他就会根据地址格式和套接字类别,自动为你选择一个合适的协议。

这是推荐使用的一种选择协议的方式。

3.intbind(SOCKETs,conststructsockaddrFAR*name,intnamelen):

a.第一个参数指定要绑定的套接字,第二个参数指定该套接字的本地地址信息,是指向sockaddr结构的指针变量,由于该地址结构是为了所有的地址家族准备使用的,这个结构可能(通常会)随使用的网络协议不同而不同,所以,要用第三个参数指定该地址结构的长度。

sockaddr机构定义如下:

structsockaddr

{

u_shortsa_family;

charsa_data[14];

}

b.上述结构第一个字段指定该地址家族,在这里必须设为AF_INET。

sa_data仅仅是表示要求一块内存分配区,起到占位的作用,该区域中指定与协议相关的具体地址信息。

由于实际要求的只是内存区,所以对于不同的协议家族,用不同的结构来替换sockaddr。

在TCP/IP中,我们可以用SOCKADDR_IN结构来代替sockaddr,以方便我们填写地址信息。

c.structSOCKADDR_IN{

shortsin_family;

unsignedshortsin_port;

structin_addrsin_addr;

charsin_zero[8];

};

sin_family表示地址族,对于IP地址,sin_family成员将一直是AF_INET;成员sin_port指定的将要分配给套接字的端口;成员sin_addr给出的是套接字的主机IP地址;sin_zero只是一个填充数,以使sockaddr_in结构和sockaddr结构的长度一样,一般不用设置。

除了sin_family外,SOCKADDR_IN其他成员是按网络字节顺序表示的。

所以需要进行转换:

htonl(INADDR_ANY),htons(6000),其中6000是端口号。

另外结构体的名称大写和小写指的是同一个。

将IP地址指定为INADDR_ANY,允许套接字向任何分配给本机器的IP地址发送或接收数据。

一般一台机器一个网卡,但对于多网卡的机器,INADDR_ANY将简化应用程序的编写。

将地址指定为INADDR_ANY,允许一个独立的应用接受发自多个接口的回应。

如果我们只想让套接字使用多个IP中的一个地址,必须指定实际地址,要做到这一点,可以用inet_addr()函数,这个函数需要一个IP地址(如192.168.80.88),返回一个适合分配给S_addr的u_long类型的数值。

Inet_ntoa()函数完成相反的转换,它接受一个in_addr结构体类型的参数并返回一个以点分十进制的IP地址字符串。

htonl把一个u_long类型从主机字节序转换为网络字节序。

htons把一个u_short类型从主机字节序转换为网络字节序。

4.intlisten(SOCKETs,intbacklog):

将套接字设置为监听模式,其中第二个参数设置等待请求连接的最大的值,即如果设置为n,则前n个请求会放置在系统的请求连接队列中,应用程序会依次对这些请求进行服务,但第n+1个连接请求则会被拒绝。

5.SOCKETaccept(SOCKETs,conststructsockaddrFAR*addr,intFAR*addrlen):

从客户端接收请求,并创建连接,如果连接成功,则会返回一个当前成功建立连接的套接字,该套接字不是上面创建的监听套接字,而是仅仅适用于当前的一个请求连接,如果建立连接失败,则返回值是INVALID_SOCKET,并且可以适用WSAGetLastError()函数得到相关的失败信息,具体的errorcode具体意义见MSDN中accept函数的最后部分的介绍

6.send函数:

向客户端发送指定信息

7.recv函数:

得到从客户端传递过来的信息

8.closesocket(SOCKETs):

将指定的套接字关闭,从而释放资源

9.WSACleanup():

终止对winsocket库的使用

10.hello

服务器端的实现过程(Win32控制台程序):

说明:

1.对于winsock库的类的使用,必须包含winsock2.h头文件

2.在setting中的link下的object/librarymodules中添加“ws2_32.lib”,注意和前面的字段之间用空格分隔

3.本服务器程序先于服务器端启动

#include"winsock2.h"

#include"stdio.h"

voidmain()

{

//加载套接字(winsock)库,加载这段代码拷贝于MSDN中WSAStartup的介绍

WORDwVersionRequested;

WSADATAwsaData;

interr;

wVersionRequested=MAKEWORD(1,1);//版本号为1.1

err=WSAStartup(wVersionRequested,&wsaData);

if(err!

=0){

return;

}

if(LOBYTE(wsaData.wVersion)!

=1||HIBYTE(wsaData.wVersion)!

=1){

WSACleanup();

return;

}

//创建套接字

SOCKETsockServer=socket(AF_INET,SOCK_STREAM,0);//SOCK_STREAM参数设置为TCP连接

SOCKADDR_INaddrServer;//设置服务器端套接字的相关属性

addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//设置IP

addrServer.sin_family=AF_INET;

addrServer.sin_port=htons(1234);//设置端口号

//将套接字绑定到本地地址和指定端口上

bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));

//将套接字设置为监听模式,并将最大请求连接数设置成5,超过此数的请求全部作废

listen(sockServer,5);

SOCKADDR_INaddrClient;//用来接收客户端的设置,包括IP和端口

intlen=sizeof(SOCKADDR);

while

(1)//不断监听

{

//得到创建连接后的一个新的套接字,用来和客户端进行沟通,原套接字继续监听客户的连接请求

SOCKETsockConn=accept(sockServer,(SOCKADDR*)&addrClient,&len);

if(sockConn!

=INVALID_SOCKET)//创建成功

{

charsendInfo[100];

//inet_ntoa将结构转换为十进制的IP地址字符串

sprintf(sendInfo,"welcome%stothistest!

",inet_ntoa(addClient.sin_addr));

//成功建立连接后向客户端发送数据,结果将显示在客户端上

send(sockConn,sendInfo,strlen(sendInfo)+1,0);

//从客户端接收数据,结果显示在服务器上

charrecvInfo[100];

recv(sockConn,recvInfo,100,0);

printf("%s\n",recvInfo);

//将本次建立连接中得到套接字关闭

closesocket(sockConn);

}

else

{

interrCode=WSAGetLastError();

printf("theerrcodeis:

%d\n",errCode);

}

}

//如果本程序不是死循环,那么在此处还应添加以下代码:

closesocket(sockServer);//对一直处于监听状态的套接字进行关闭

WSACleanup();//终止对winsocket库的使用

}

创建基于TCP协议的CS程序的Client端所涉及的相关函数说明(按使用的先后顺序排列):

1.intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData):

说明同上

2.SOCKETsocket(intaf,inttype,intprotocol):

说明同上

3.connect函数:

同服务器建立连接

4.send/recv:

发送与接收,同上

5.closesocket:

关闭套接字,同上

客户端的实现过程(win32console程序):

说明:

1.对于winsock库的类的使用,必须包含winsock2.h头文件

2.在setting中的link下的object/librarymodules中添加“ws2_32.lib”,注意和前面的字段之间用空格分隔

3.启动客户端程序之前必须先启动服务器端的程序

#include"winsock2.h"

#include"stdio.h"

voidmain()

{

//加载套接字库

WORDwVersionRequested;

WSADATAwsaData;

interr;

wVersionRequested=MAKEWORD(1,1);//版本好为1.1

err=WSAStartup(wVersionRequested,&wsaData);

if(err!

=0){

return;

}

if(LOBYTE(wsaData.wVersion)!

=1||HIBYTE(wsaData.wVersion)!

=1){

WSACleanup();

return;

}

SOCKETsockClient=socket(AF_INET,SOCK_STREAM,0);//SOCK_STREAM参数设置为TCP连接

SOCKADDR_INaddrServer;//服务器地址结构

addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//服务器地址

addrServer.sin_port=htons(1234);//服务器端口号

addrServer.sin_family=AF_INET;

//与服务器端建立连接,进行通信

intconnReult=connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));

if(connReult!

=WSAEADDRNOTAVAIL)//访问成功

{

//成功建立连接后向服务器端发送数据,结果将显示在服务器端上

send(sockClient,"thisislisi!

",strlen("thisiszhangsan!

")+1,0);

//接收来自服务器端发送来的信息

charrecvInfo[100];

recv(sockClient,recvInfo,100,0);

printf("%s\n",recvInfo);

}

else

{

interrCode=WSAGetLastError();

printf("theerrcodeis:

%d\n",errCode);

}

closesocket(sockClient);

WSACleanup();

}

创建基于UPD的CS程序服务器端源代码:

说明:

服务器端的代码在XP下运行recvfrom函数执行不成功,返回一个10022的错误代码,参看网上资源,得知10022代表某个参数设置错误。

花了大半天的时间研究后终于发现原来是6000端口在作怪,可能本机的UDP的6000端口在防火墙中被屏蔽了,通不过,但在TCP的CS程序中6000端口是通过的,程序调试一切正常,将端口修改为其他端口即可

#include"winsock2.h"

#include"stdio.h"

voidmain()

{

//加载套接字(winsock)库,加载这段代码拷贝于MSDN中WSAStartup的介绍

WORDwVersionRequested;

WSADATAwsaData;

interr;

wVersionRequested=MAKEWORD(1,1);//版本号为1.1

err=WSAStartup(wVersionRequested,&wsaData);

if(err!

=0){

return;

}

if(LOBYTE(wsaData.wVersion)!

=1||

HIBYTE(wsaData.wVersion)!

=1){

WSACleanup();

return;

}

//创建套接字

//注意第二个参数和TCP设置不同

SOCKETsockServer=socket(AF_INET,SOCK_DGRAM,0);

SOCKADDR_INaddrServer;//设置服务器端套接字的地址结构的相关属性

addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//设置IP

addrServer.sin_family=AF_INET;

addrServer.sin_port=htons(6000);//设置端口号

//将套接字和服务器地址结构绑定

bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));

SOCKADDR_INaddrClient;

intlen=sizeof(SOCKADDR);

charbuffer[100];

//从客户端接收数据

intresult=recvfrom(sockServer,buffer,100,0,(SOCKADDR*)&addrClient,&len);

if(result==SOCKET_ERROR)

{

interrCode=WSAGetLastError();

printf("error:

%d",errCode);

}

else

{

printf("thismessagefromclient:

%s\n",buffer);

}

closesocket(sockServer);

WSACleanup();

}

创建基于UDP的CS程序客户端的代码:

#include"winsock2.h"

#include"stdio.h"

voidmain()

{

//加载套接字(winsock)库,加载这段代码拷贝于MSDN中WSAStartup的介绍

WORDwVersionRequested;

WSADATAwsaData;

interr;

wVersionRequested=MAKEWORD(1,1);//版本号为1.1

err=WSAStartup(wVersionRequested,&wsaData);

if(err!

=0){

return;

}

if(LOBYTE(wsaData.wVersion)!

=1||HIBYTE(wsaData.wVersion)!

=1){

WSACleanup();

return;

}

//创建套接字

SOCKETsockClient=socket(AF_INET,SOCK_DGRAM,0);//注意第二个参数和TCP设置不同

SOCKADDR_INaddrServer;//服务器地址结构

addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//服务器地址

addrServer.sin_family=AF_INET;

addrServer.sin_port=htons(6000);//服务器端口号

sendto(sockClient,"thismessagefromclient",strlen("thismessagefromclient")+1,0,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));

closesocket(sockClient);

WSACleanup();

}

基于UDP的聊天程序服务器端源程序:

说明:

1.代码基本和上述UDP服务器端的程序相类似,只是多了sendto功能,即交互的功能

2.支持退出请求响应

#include"winsock2.h"

#include"stdio.h"

voidmain()

{

//加载套接字(winsock)库,加载这段代码拷贝于MSDN中WSAStartup的介绍

WORDwVersionRequested;

WSADATAwsaData;

interr;

wVersionRequested=MAKEWORD(1,1);//版本号为1.1

err=WSA

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1