使用套接字进行通信

socket概念

套接字(Socket)是计算机网络编程中的一个概念,用于在网络上进行通信。它是一种抽象的通信端点,可以通过网络进行数据的发送和接收。

套接字提供了一种统一的编程接口,使得应用程序可以通过网络进行数据的传输和通信。它通过网络传输层协议(如TCP、UDP等)实现数据的可靠传输或者不可靠传输。

套接字通常由以下几个要素组成:

  1. IP地址:用于标识网络上的主机或者设备。

  2. 端口号:用于标识网络上的不同应用程序或者服务。

  3. 协议:用于指定网络传输层协议,如TCP、UDP等。

通过套接字,应用程序可以通过发送和接收数据报来进行通信。发送方将数据封装成数据报,并通过套接字发送给接收方,接收方通过套接字接收数据报并进行处理。

套接字编程是网络编程中常见的一种方式,它提供了丰富的接口和函数,用于创建、连接、发送、接收和关闭套接字等操作。在套接字编程中,可以实现各种类型的网络通信,如客户端-服务器模式、点对点通信等。

常用数据类型

	const int		BUF_SIZE = 32;
	WSADATA         wsd;              //WSADATA变量  
	SOCKET          sServer;          //服务端套接字  
	SOCKET          sClient;          //客户端套接字  
	sockaddr_in     addrServ;         //服务端地址  
	char            buf[BUF_SIZE];    //接收数据缓冲区 
	char            str1[BUF_SIZE];
	char            sendBuf[BUF_SIZE];//返回给客户端的数据  
	char			strJsonRecv[64];
	int             retVal;           //返回值 
	string			strJsonSend = "KEY_PileNo";

这段代码是一个简单的服务器端代码,用于接收客户端发送的数据,并返回给客户端一个字符串。具体解释如下:

  1. const int BUF_SIZE = 32:定义了一个常量BUF_SIZE,表示接收数据缓冲区的大小为32字节。

  2. WSADATA wsd:定义了一个WSADATA结构体变量wsd,用于接收套接字库的初始化信息。

  3. SOCKET sServerSOCKET sClient:分别定义了服务端套接字和客户端套接字,用于接收和处理客户端的连接请求。

  4. sockaddr_in addrServ:定义了一个sockaddr_in结构体变量addrServ,用于存储服务端的地址信息。

  5. char buf[BUF_SIZE]char str1[BUF_SIZE]char sendBuf[BUF_SIZE]:分别定义了接收数据缓冲区、字符串变量和用于返回给客户端的数据缓冲区。

  6. char strJsonRecv[64]:定义了一个大小为64字节的字符数组strJsonRecv,用于接收客户端发送的JSON数据。

  7. int retVal:定义了一个整型变量retVal,用于存储函数调用的返回值。

  8. string strJsonSend = "KEY_PileNo":定义了一个字符串变量strJsonSend,并初始化为"KEY_PileNo",该字符串将作为返回给客户端的数据。

常用函数

WSAStartup()

WSAStartup(MAKEWORD(2,2), &wsd)

WSAStartup是Windows套接字库提供的函数,用于初始化套接字库。MAKEWORD(2,2)是一个宏,用于指定套接字库的版本号,这里是指定使用2.2版本的套接字库。&wsd是一个指向WSADATA结构体的指针,用于接收套接字库的初始化信息。WSAStartup函数返回0表示初始化成功,如果返回值不为0,则表示初始化失败。

socket(); 

sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  

socket函数用于创建一个套接字。AF_INET表示使用IPv4地址族,SOCK_STREAM表示创建一个面向连接的套接字,IPPROTO_TCP表示使用TCP协议。常用if(INVALID_SOCKET == sServer)判断socket函数返回的套接字是否为无效套接字。INVALID_SOCKET是一个宏,表示无效的套接字。

WSACleanup()

WSACleanup函数用于释放套接字库所占用的资源,包括关闭套接字库并释放其它相关资源。

上面socket()套接字创建失败可能是由于系统资源不足或者套接字库初始化失败等原因。所以在失败后,往往会跟进一步WSACleanup函数。

htons() 

htons函数用于将主机字节序的端口号转换为网络字节序的端口号。例如设置端口号:

addrServ.sin_port=htons(m_nPort);  //设置端口号

m_nPort是一个变量,表示要设置的端口号。通过调用htons函数将主机字节序的端口号转换为网络字节序后,将结果赋值给addrServ.sin_port,实现了设置端口号的操作。

网络字节序是一种统一的网络数据传输格式,不受不同主机字节序的影响,因此在套接字编程中常常需要进行字节序的转换。

bind()

retVal = bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));

用于将套接字(socket)与指定的地址绑定起来。具体解释如下:

  1. retValretVal是一个变量,用于接收bind()函数的返回值。bind()函数成功时返回0,失败时返回-1。

  2. sServersServer是一个套接字描述符,表示要绑定的套接字。

  3. (LPSOCKADDR)&addrServ&addrServ表示指向addrServ的指针,LPSOCKADDR是指向SOCKADDR结构体的指针,用于指定要绑定的地址。

  4. sizeof(SOCKADDR_IN)sizeof(SOCKADDR_IN)用于获取SOCKADDR_IN结构体的大小,即要绑定的地址的长度。

通过调用bind()函数将套接字与addrServ所指定的地址绑定起来,将绑定结果赋值给retVal,以便后续判断绑定是否成功。绑定后,该套接字就可以使用指定的地址进行通信。

类似的,如果绑定失败,是需要关闭套接字并释放资源的。

closesocket(sServer);   //关闭套接字  
WSACleanup();           //释放套接字资源;

listen()

用于将套接字(socket)设置为监听状态,以便接受客户端的连接请求。例如

retVal = listen(sServer, 1);

具体解释如下:

  1. retValretVal是一个变量,用于接收listen()函数的返回值。listen()函数成功时返回0,失败时返回-1。

  2. sServersServer是一个套接字描述符,表示要设置为监听状态的套接字。

  3. 11表示设置监听队列的最大长度。这个参数指定了在调用listen()函数后,等待连接的客户端能够排队的最大数量。在这个例子中,将最大排队长度设置为1,表示在某一时刻只能接受一个客户端的连接请求。

通过调用listen()函数,将套接字设置为监听状态,以便开始接受客户端的连接请求。设置监听后,套接字将开始监听指定端口上的连接请求,并将这些请求排队等待处理。retVal变量用于接收函数的返回值,以便后续判断监听是否成功。

accept()

sClient = accept(sServer,(sockaddr FAR*)&addrClient, &addrClientlen); 

用于接受客户端的连接请求,并创建一个新的套接字来与客户端进行通信。具体解释如下:

  1. sClientsClient是一个套接字描述符,用于表示与客户端建立的新连接。

  2. accept()函数:accept()函数用于接受客户端的连接请求,并创建一个新的套接字来与客户端进行通信。它的第一个参数sServer是一个套接字描述符,表示正在监听的套接字。accept()函数会从监听队列中选择一个连接请求,并返回一个新的套接字描述符,用于与客户端通信。

  3. (sockaddr FAR*)&addrClient(sockaddr FAR*)&addrClient是一个指向sockaddr结构体的指针,用于存储客户端的地址信息。sockaddr结构体是一个通用的套接字地址结构,可以根据实际情况使用不同的具体类型,如sockaddr_in用于IPv4地址,sockaddr_in6用于IPv6地址等。

  4. &addrClientlen&addrClientlen是一个整型变量的指针,用于传递客户端地址结构体的长度。在调用accept()函数之前,需要将addrClientlen初始化为socklen_t类型的长度值。

通过调用accept()函数,可以接受客户端的连接请求,并创建一个新的套接字sClient来与客户端进行通信。新的套接字sClient将成为与客户端之间的通信通道,可以通过该套接字进行数据的发送和接收。

setsockopt()

setsockopt函数用于设置套接字选项的值。它的原型如下:

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

 例如用它来设置套接字的发送超时时间:

int timeout = 6000; 
int retSend=setsockopt(m_SocketClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));
int retRecv=setsockopt(m_SocketClient,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
  • sockfd:套接字描述符,用于标识要设置选项的套接字。
  • level:选项所属的协议层,常用的是SOL_SOCKET表示套接字级别选项。
  • optname:选项的名称,常用的是SO_SNDTIMEO表示发送超时时间选项、SO_RCVTIMEO表示接收超时时间选项。
  • optval:选项的值,是一个指向选项值的指针。
  • optlen:选项值的长度。

在这个例子中,m_SocketClient是要设置选项的套接字描述符。SOL_SOCKET表示套接字级别选项,SO_SNDTIMEO表示发送超时时间选项,SO_RCVTIMEO表示接收超时时间选项。&timeout是一个指向超时时间值的指针,sizeof(timeout)表示超时时间值的长度。

recv()

retVal = recv(sClient, buf, BUF_SIZE, 0);

用于从客户端接收数据,并将接收到的数据存储在缓冲区buf中。具体解释如下:

  1. retValretVal是一个整型变量,用于存储recv()函数的返回值。recv()函数返回接收到的字节数,如果返回值为0,则表示客户端已关闭连接,如果返回值为-1,则表示接收出现错误。

  2. recv()函数:recv()函数用于从指定的套接字sClient接收数据。它的第一个参数sClient是一个套接字描述符,表示要接收数据的套接字。第二个参数buf是一个指向缓冲区的指针,用于存储接收到的数据。第三个参数BUF_SIZE表示要接收的最大数据长度。第四个参数0表示接收数据时不使用任何特殊的标志。

通过调用recv()函数,可以从客户端接收数据,并将接收到的数据存储在缓冲区buf中。recv()函数将返回接收到的字节数,并将其赋值给retVal变量。根据retVal的值,可以判断接收是否成功,以及客户端是否已关闭连接。

send()

send(sClient,sendBuf,strlen(sendBuf),0);

 send函数是套接字编程中用于发送数据的函数。它的第一个参数是要发送数据的套接字描述符,第二个参数是一个指向要发送的数据的缓冲区的指针,第三个参数是要发送的数据的长度,第四个参数是发送操作的标志,0表示使用默认的发送选项。

ZeroMemory()

ZeroMemory(buf, BUF_SIZE);

ZeroMemory函数:ZeroMemory函数是Windows API提供的一个宏,用于将指定内存块的内容全部设置为零。它的第一个参数是要清零的内存块的指针,第二个参数是内存块的大小。

通过调用ZeroMemory函数,可以将缓冲区buf的内容全部清零,即将缓冲区的每个字节设置为0。这样可以确保在接收新的数据之前,缓冲区中没有之前接收到的旧数据。

strcpy_s()

strcpy_s(sendBuf, strlen(strJsonSend.c_str())+1, strJsonSend.c_str());

strcpy_s函数是C语言中的字符串拷贝函数,用于将一个字符串复制到另一个字符串。它的第一个参数是目标字符串的指针,第二个参数是目标字符串的大小,第三个参数是要复制的源字符串的指针。在这里,strlen(strJsonSend.c_str())+1表示源字符串的长度加上一个字节,用于存储字符串的结束符\0

猜你喜欢

转载自blog.csdn.net/weixin_55696427/article/details/134433786
今日推荐