2024年4月28日发(作者:)

TCP/UDP通信编程入门(C++)

与UDP连接模式的比较

TCP:Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可

靠的、基于字节流的运输层(Transport layer)通信协议.

UDP:User Datagram Protocol 用户数据报协议(UDP)是 OSI 参考模型中一种无连

接的传输层协议,提供面向事务的简单不可靠信息传送服务.

有关这两种模式如果你想了解更多的话,看这儿 :/?syn=TCP

/

a).TCP Server创建流程:

WSAStartup(...)->socket(...)->bind(...)->listen(...)->accept(...)->recv(...)->closesocket(...)->

WSACleanup();

TCP Client创建流程:

WSAStartup(...)->socket(...)->bind(...)->connect(...)->send(...)->closesocket(...)->

WSACleanup();

b).UDP Server创建流程:

WSAStartup(...)->socket(...)->bind(...)->recvfrom(...)->closesocket(...)->WSACleanup();

UDP Client创建流程:

WSAStartup(...)->socket(...)->sendto(...)->closesocket(...)->WSACleanup();

上面的不用记,等下面的函数讲解完,函数理解了,也就自然串起来了。

函数解析:

①int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData );本函数初始化

winsock库

EG:

WSADATA wsa;

WSAStartup(MAKEWORD(2,2),&wsa);//MAKEWORD将前面的2和后面的2组成一个新的

WORD。生成一个版本号。MAKEWORD(a,b),a=2,1;b=1,0;都可以。当然你用

0x101,0x200,0x202也没错。

②SOCKET socket( int af, int type, int protocol );

第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置

AF_INET;

第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类

型为SOCK_DGRAM;

第三个参数指定应用程序所使用的通信协议。 如果协议protocol未指定(等于0),则使用

缺省的连接方式。(这个通常设置为0)。

EG:

socket(AF_INET,SOCK_STREAM,0);

③int bind( SOCKET s, const struct sockaddr FAR* name,int namelen);

sockaddr结构定义如下:struct sockaddr{

u_short sa_family;

char sa_data[14];

};

在使用这个函数之前,必须要对结构体sockaddr_in的结构变量初始化。struct sockaddr_in {

short int sin_family; /* Address family */

unsigned short int sin_port; /* Port number */

struct in_addr sin_addr; /* Internet address */

unsigned char sin_zero[8]; /* Same size as struct sockaddr */

//这个不用管,只是为了使结构体与sockaddr_in结构体长度匹

配.

};

这儿因为要绑定主机,所以必须用结构体sockaddr_in的结构变量记录主机信息。然后在强

制类型转换成sockaddr类型。应该不难理解吧~

EG:

sockaddr_in mycomputerinfo;

_family=AF_INET;

_port=htons(端口号) //服务端端口,这里要用htons函数将端口从本地字

节序转换为网络字节序才能使用。具体参见/view/

_addr.s_addr=inet_addr(IP); //服务端IP地址。对IP的初始化还有另外一种

方式。具体记不清了,自己查阅一下吧。inet_addr(...)函数将字符串转换为32位整数。因为

我们输入的IP地址是字符串,所以要转换的。

④int listen( SOCKET s, int backlog); //这个函数没什么要讲的。最后一个参数是等待连接对列

的最大 长度。

⑤SOCKET accept( SOCKET s, struct sockaddr FAR* addr,int FAR* addrlen);

这个函数用于服务端,进行通信连接用的。

注意喽,这儿是个重点。对于TCP连接来说,有两个套接字,一个监听套接字,一个会话

套接字。 在这个函数之前使用的套接字为监听套接字,在这个函数及之后使用的套接字则

为会话套接字。

再讲讲这两个套接字的运行过程,我们首先是定义了一个监听套接字使用函数 listen(...)

去监听来自客户端的连接请求,当我们的监听套接字接收到连接请求,把连接请求传递给会

话套接字,然后在从消息队列中取出下一条消息,如果没有消息的话,则处于等待状态。而

accept(...)函数接收到连接请求后,则会建立起服务端与客户端的连接,为后面的通信做

准备。我这么说,你应该明白吧,很简单的。

⑥ int connect( SOCKET s, const struct sockaddr FAR* name, int namelen);

这个函数用于客户端,进行通信连接用的。

⑦int recv( SOCKET s, char FAR* buf, int len, int flags); //该函数用于服务端。

s:一个标识已连接套接口的描述字。 buf:用于接收数据的缓冲区。 len:缓冲区

长度。 flags:指定调用方式

⑧int send( SOCKET s, const char FAR* buf, int len, int flags); //该函数用于服务端。

s:一个标识已连接套接口的描述字。 buf:包含待发送数据的缓冲区。 len:缓冲区长度。