面向连接的c语言/socket 程序流程(TCP)

 先看流程图,再看图解释。

      (纯手绘)
一. WSAStartup 

函数原型

   int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData);

为了在应用程序中调用任何一个Winsock API函数,需要WSAStartup函数完成对Winsock初始化,使用Socket的程序在使用

Socket之前必须调用WSAStarup.

第一个参数是使用Socket字节的版本,高位字节指明副版本,低位字节指明主版本。

操作系统根据第二个参数返回Socket的版本

二.Socket

函数原型

int Socket(int domain,int type,int protocol);

domain指明所使用的协议族,通常为PF_INET/AF_INET,表示互联网协议族(TCP/IP协议族);

type参数指定socket的类型:SOCK_STREAM(TCP)或SOCK_DGRAM(UDP),Socket接口还定义了原始Socket(SOCK_RAW),

允许程序使用低层协议;

protocol通常赋值‘0’.

Socket()调用返回一个整形socket()描述符,你可以在后面的调用使用它。

三. bind()--指定本地地址

当socket()创建了一个套接字后,需要将该套接字与该主机上提供服务的某个端口联系在一起,

bind()函数用于完成这样的绑定。

int bind(

       SOCKET s,//标识一个未绑定的套接字描述符 ,它是socket()函数调用成功时返回的值

   

        const struct sockaddr FAR* name,//是一个与指定协议有关的地址结构指针,存储了套接字的地址信息,

//Winsock中使用sockaddr_in结构指定IP地址和端口信息

        int namelen

)

  struct sockaddr_in{

        short sin_family;//一般为AF_INET,表示使用IP地址族;

        u_short sin_port;//是以网络字节序表示的16位端口号;

        struct in_addr sin_addr;//是网络字节序的32位IP地址;

        char       sin_zero[8];//一般不用,用0填充

}

四.服务器启动监听——listen()函数

在一个服务器用socket()调用成功创建了一个套接字,并用bind()函数和一个指定的地址关联后,

就需要指示该套接字进入监听连接请求状态,这需要通过listen()函数来实现

            int listen(

                SOCKET s,//一个已绑定地址,但还未建立连接的套接字描述字

                int backlog//指定了正在等待连接的最大队列长度

五.客户端请求连接——connect()函数

当服务器端建立好套接字并与一个本地地址绑定后,就进入监听状态,

等待客户发出连接请求。在客户端套接字建立好之后,就调用connect()函数来与服务器建立连接

            int connect(

            SOCKET s,//s:标识一个未连接socket

            const struct sockaddr FAR * name,//指向要连接套接字的sockaddr结构体的指针

            int namelen//sockaddr结构体的字节长度

        )

六.服务器端接收连接——accept()函数

在服务器端通过listen()函数调用表示服务器进入监听客户的连接状态请求,而在服务器端调用

accept()函数时表示可以接收来自客户端由connect()发出的连接请求,双方进入连接状态

  

SOCKET accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:套接字描述符,该套接口在listen()后监听连接。

addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。

addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数。

七.send()函数

int PASCAL FAR send( SOCKET s, const char FAR* buf, int len, int flags);

s:一个用于标识已连接套接口的描述字。

buf:包含待发送数据的缓冲区

len:缓冲区中数据的长度。

flags:调用执行方式。


send()是一个计算机函数,功能是向一个已经连接的socket发送数据,如果无错误,返回值为所发送数据的总数,否则返回SOCKET_ERROR。

八.无连接的套接字上接收数据——recvfrom()

本函数用于从(已连接)套接口上接收数据,并捕获数据发送源的地址。

int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,

struct sockaddr FAR* from, int FAR* fromlen);

s:标识一个已连接套接口的描述字。

buf:接收数据缓冲区

len:缓冲区长度。

flags:调用操作方式。

from:(可选)指针,指向装有源地址的缓冲区。

fromlen:(可选)指针,指向from缓冲区长度值。

九.关闭套接字——closesocket()函数

本函数关闭一个套接口。更确切地说,它释放套接口描述字s,以后对s的访问均以WSAENOTSOCK错误返回。若本次为对套接口的最后一次访问,则相应的名字信息及数据队列都将被释放。

一个套接字不再使用时一定要关闭这个套接字,以释放与该套接字关联的所有资源,包括等候处理的数据

int PASCAL FAR close socket( SOCKET s);
s:被关闭的套接口的描述字。

十.WSACleanup()


#include <Winsock2.h>

引用库

#pragma comment(lib, "ws2_32.lib")
静态加入一个 lib文件也就是库文件ws2_32.lib文件,提供相关API的支持,否则需要动态载入 ws2_32.dll

函数原型


int PASCAL FAR WSACleanup (void);

返回值

操作成功返回值为0;否则返回值为SOCKET_ERROR,可以通过调用WSAGetLastError获取错误代码。
在一个多线程的环境下,WSACleanup()中止了Windows Sockets在所有线程上的操作.














猜你喜欢

转载自blog.csdn.net/qq_41603898/article/details/81047598