WinSocket API —— 关闭closesocket后收发数据

WinSocket API —— 收发数据

然后是进行数据的传输,发送数据send:

建立连接后,服务器端的sockConn与客户端的sockClient就连接起来并且可以互相传输数据了,

int send(

SOCKET s,                    //连接socket,非监听socket

const char FAR *buf,     //要发送数据buf的地址

int len,                         //buf的长度

int flags                        //一般设置为0即可。

); 

接收数据使用recv函数

int recv(

SOCKET s,              

char FAR *buf,         //要发送数据buf的地址。

int len,                     //要接收数据buf的长度

int flags                    //一般设置为0即可。

);

  

    

使用closesocket函数关闭其中一端socket后,连接断开发生的各种情况:

关闭socketA之后:

对socketA使用recv函数接收数据,和使用send函数发送数据,都会马上返回SOCKET_ERROR。

之后另一端socketB:

1.socketB第一次send函数能成功返回发送数据的大小,并不会返回SOCKET_ERROR 。但socketA是无法接收到的。之后socketB使用send函数返回的都是SOCKET_ERROR 。

2.socketB使用recv函数接收数据。如果socketB之前没有使用send函数,那么recv函数的返回值总是0。直到socketB调用过send函数之后,recv函数的返回值总是SOCKET_ERROR。

因此要考虑A端和B端如何协调关闭连接。socketA想要关闭连接,除了closesocket(socketA)之外,还要另外通知socketB,不然socketB还在那里傻傻的接收/发送数据。

如果不想显式的通知,socketB就要自己判断,如果socketB多次调用send函数总是返回SOCKET_ERROR或者socketB多次调用recv函数总是返回0或SOCKET_ERROR,那就要意识到连接很可能已经断开了。

 

数据的流向是单向的:

例如说数据只从socketA流向socketB(类似文件传输就是这样),那么socketA只会调用send函数,而socketB只会调用recv函数,这时候如果其中一方要停止数据的传输,就会有两种情况出现:

1.如果socketA的计算机不想发送数据而closesocket(socketA),由于socketB从来不调用send函数,因此socketB的recv函数总是返回0,那么socketB的计算机就要意识到socketA很可能已经关闭了,让socketB的计算机closesocket(socketB)。

2.如果socketB的计算机不想接收数据而closesocket(socketA),这时socketA继续调用send函数发送数据,第一次send还是成功的,但从第二次send开始就总会返回SOCKET_ERROR,但是socketA的计算机无法判断send函数返回SOCKET_ERROR是由socketB关闭造成的还是Asocket关闭造成的(因为socketA关闭后socketA调用send函数也是返回SOCKET_ERROR),因此socketA的计算机无法判断socketA关闭了没有,简单的解决方法是如果socketB的计算机不想接收数据,先不要关闭socketB,而是发通知给Asocket的计算机告诉它我不想收数据了,socketA的计算机收到通知后关闭socketA,这样情形就回到上面情况1去了,而且也知道socketA调用send函数返回SOCKET_ERROR肯定是由于socketA关闭造成的而不是由socketB关闭造成的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个经典的 Socket 编程问题,我可以为您提供一些基本的思路和代码示例。 首先,服务端和客户端都需要创建一个 Socket 对象,以便进行通信。在 C 语言中,可以使用 Winsock 库来实现 Socket 编程。以下是服务端和客户端的代码示例。 服务端代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <winsock2.h> int main() { // 初始化 Winsock 库 WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); return 1; } // 创建 Socket 对象 SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listenSocket == INVALID_SOCKET) { printf("Error creating socket: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } // 绑定 Socket 对象到本地地址和端口 struct sockaddr_in localAddr; localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = INADDR_ANY; localAddr.sin_port = htons(12345); iResult = bind(listenSocket, (struct sockaddr*) &localAddr, sizeof(localAddr)); if (iResult == SOCKET_ERROR) { printf("Bind failed: %d\n", WSAGetLastError()); closesocket(listenSocket); WSACleanup(); return 1; } // 开始监听客户端连接请求 iResult = listen(listenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("Listen failed: %d\n", WSAGetLastError()); closesocket(listenSocket); WSACleanup(); return 1; } // 等待客户端连接 printf("Waiting for client connection...\n"); SOCKET clientSocket = accept(listenSocket, NULL, NULL); if (clientSocket == INVALID_SOCKET) { printf("Accept failed: %d\n", WSAGetLastError()); closesocket(listenSocket); WSACleanup(); return 1; } // 接收和发送数据 char recvBuf[1024]; char sendBuf[1024]; while (1) { // 接收客户端发来的数据 iResult = recv(clientSocket, recvBuf, sizeof(recvBuf), 0); if (iResult > 0) { recvBuf[iResult] = '\0'; printf("Received: %s\n", recvBuf); // 发送数据给客户端 sprintf(sendBuf, "Hello, %s!", recvBuf); iResult = send(clientSocket, sendBuf, strlen(sendBuf), 0); if (iResult == SOCKET_ERROR) { printf("Send failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } } else if (iResult == 0) { printf("Connection closed.\n"); break; } else { printf("Recv failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } } // 关闭 Socket 对象 closesocket(clientSocket); closesocket(listenSocket); WSACleanup(); return 0; } ``` 客户端代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <winsock2.h> int main() { // 初始化 Winsock 库 WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); return 1; } // 创建 Socket 对象 SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (clientSocket == INVALID_SOCKET) { printf("Error creating socket: %ld\n", WSAGetLastError()); WSACleanup(); return 1; } // 连接到服务端 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(12345); iResult = connect(clientSocket, (struct sockaddr*) &serverAddr, sizeof(serverAddr)); if (iResult == SOCKET_ERROR) { printf("Connect failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } // 接收和发送数据 char recvBuf[1024]; char sendBuf[1024]; while (1) { // 发送数据给服务端 printf("Enter message: "); fgets(sendBuf, sizeof(sendBuf), stdin); sendBuf[strlen(sendBuf)-1] = '\0'; iResult = send(clientSocket, sendBuf, strlen(sendBuf), 0); if (iResult == SOCKET_ERROR) { printf("Send failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } // 接收服务端发来的数据 iResult = recv(clientSocket, recvBuf, sizeof(recvBuf), 0); if (iResult > 0) { recvBuf[iResult] = '\0'; printf("Received: %s\n", recvBuf); } else if (iResult == 0) { printf("Connection closed.\n"); break; } else { printf("Recv failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } } // 关闭 Socket 对象 closesocket(clientSocket); WSACleanup(); return 0; } ``` 以上代码示例只是基本的实现,您可以根据自己的需要进行进一步的修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值