首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Visual C++中接受来自客户端的连接(套接字编程)时出现问题

在Visual C++中接受来自客户端的连接(套接字编程)时出现问题
EN

Stack Overflow用户
提问于 2010-10-25 02:02:29
回答 4查看 5K关注 0票数 0

我已经用Visual C++编写了一个简单的单线程客户端服务器应用程序。当我运行我的服务器时,我会等待一段时间,直到它接受来自客户端的一些请求。

当我将客户端连接到服务器时。客户端上的日志消息报告发送了14个字节,而服务器上没有消息。我已经编写了一条print语句,用于在控制台上打印服务器接受的任何内容,但服务器不打印任何内容。

在我看来,客户端似乎已经连接到了其他服务器。

客户端和服务器代码如下所示。

服务器代码

代码语言:javascript
复制
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <conio.h>

#define DEFAULT_PORT        "27015"
#define DEFAULT_BUFLEN        512
#pragma comment(lib, "Ws2_32.lib")

int main() {
    WSADATA wsdata;
    int result = WSAStartup(MAKEWORD(2,2),&wsdata);
    if (result != 0){
        printf("%s","Unable to initilize windows socket\n");
        getch();
        return 1;
    }

    struct addrinfo *addrResult = NULL,hints;
    ZeroMemory(&hints, sizeof (hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    result = getaddrinfo(NULL,DEFAULT_PORT,&hints,&addrResult);
    if (result != 0){
        printf("%s","Error in getaddrInfo");
        getch();
        return 1;
    }
    SOCKET listenSocket = INVALID_SOCKET;
    listenSocket = socket(addrResult->ai_family,addrResult->ai_socktype,addrResult->ai_protocol);

    if (listenSocket == INVALID_SOCKET){
        printf("%s","Error in creating socket object\n");
        getch();
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr("127.0.0.1");
    service.sin_port = htons(27015);

    if (bind(listenSocket,addrResult->ai_addr,
        (int)addrResult->ai_addrlen) == SOCKET_ERROR){
    //if(bind(listenSocket,(SOCKADDR*) &service,
    //    sizeof(service)) == SOCKET_ERROR){

        printf("bind failed: %d\n", WSAGetLastError());
        freeaddrinfo(addrResult);
        closesocket(listenSocket);
        WSACleanup();
        getch();
        return 1;
    }
    freeaddrinfo(addrResult);
    if (listen(listenSocket,SOMAXCONN) == SOCKET_ERROR){
        printf("%s","Error in listening socket");
        getch();
        closesocket(listenSocket);
        WSACleanup();
    }
    SOCKET clientSocket = INVALID_SOCKET;
    clientSocket = accept((listenSocket,NULL,NULL);
    if (clientSocket ==  INVALID_SOCKET){
        closesocket(listenSocket);
        WSACleanup();
    }

    char recvbuf[DEFAULT_BUFLEN];
    int iRecvResult, iSendResult;
    int recvbuflen = DEFAULT_BUFLEN;

    do{
        iRecvResult = 0;
        iSendResult = 0;
        iRecvResult = recv(clientSocket,recvbuf,recvbuflen,0);
        if (iRecvResult > 0){
            printf("Bytes received: %d\n", iRecvResult);
            getch();
            // Echo the buffer back to the sender
            iSendResult = send(clientSocket, recvbuf, iRecvResult, 0);
            if (iSendResult == SOCKET_ERROR) {
                printf("send failed: %d\n", WSAGetLastError());
                closesocket(clientSocket);
                WSACleanup();
                return 1;
            }
            printf("Bytes sent: %d\n", iSendResult);
        }
        else if (iRecvResult == 0){
            printf("Connection closing...\n");
        }
        else{
            printf("recv failed: %d\n", WSAGetLastError());
            closesocket(clientSocket);
            WSACleanup();
            return 1;
        }
    }while(iRecvResult > 0);
  getch();
  return 0;
}

客户端代码

代码语言:javascript
复制
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <conio.h>

#define DEFAULT_PORT        "27015"
#define DEFAULT_BUFLEN        512
#pragma comment(lib, "Ws2_32.lib")

int main(){
    WSADATA wsdata;
    WSAStartup(MAKEWORD(2,2),&wsdata);
    struct addrinfo *addrResult = NULL,hints;
    ZeroMemory(&hints, sizeof (hints));
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_family = AF_UNSPEC;
    int result = 0;
    if (getaddrinfo("127.0.0.1",DEFAULT_PORT,
        &hints,&addrResult)){
            printf("%s","Error in getaddrInfo\n");
            WSACleanup();
            getch();
            return 1;
    }
    SOCKET connectingSocket = INVALID_SOCKET;
    connectingSocket = socket(addrResult->ai_family,addrResult->ai_socktype,
        addrResult->ai_protocol);
    if (connectingSocket == INVALID_SOCKET){
        printf("%s","Error in creating socket\n");
        freeaddrinfo(addrResult);
        WSACleanup();
        getch();
        return 1;
    }

    if (connect(connectingSocket,addrResult->ai_addr, (int)addrResult->ai_addrlen) != 0){
        closesocket(connectingSocket);
        connectingSocket = INVALID_SOCKET;
        WSACleanup();

    }
    freeaddrinfo(addrResult);

    int recvbuflen = DEFAULT_BUFLEN;
    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];

    int iResult;

    // Send an initial buffer
    iResult = send(connectingSocket, sendbuf, (int) strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        printf("send failed: %d\n", WSAGetLastError());
        closesocket(connectingSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection for sending since no more data will be sent
    // the client can still use the connectingSocket for receiving data
    iResult = shutdown(connectingSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(connectingSocket);
        WSACleanup();
        return 1;
    }

    // Receive data until the server closes the connection
    do {
        iResult = recv(connectingSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0)
            printf("Bytes received: %d\n", iResult);
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());
    } while (iResult > 0);

    getch();
    return 0;
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-10-25 02:37:38

Hmm...after修复了明显的语法错误(clientSocket = accept((listenSocket,NULL,NULL);中不匹配的左括号),对我来说似乎工作得还不错。在服务器上,我得到:

接收的

字节数: 14

发送的字节数: 14

连接正在关闭...

在客户端:

发送的

字节数: 14

接收的字节数: 14

接收失败: 10054

因此,客户端向服务器发送14个字节(按enter键),服务器将这14个字节回送给客户端(再次按enter键),然后服务器关闭连接。客户端读取14个字节,然后在连接关闭时进一步读取失败。

编辑:我通过打开两个windows SDK命令提示符窗口来运行代码,在一个窗口中运行server,在另一个窗口中运行client --这两个窗口都没有什么特别令人兴奋或不寻常的地方。

票数 1
EN

Stack Overflow用户

发布于 2010-10-25 02:11:17

当客户端尝试发送时,您可以通过增强诊断来确认服务器代码中发生了什么。在重要时刻(例如,成功的connect()accept()close()、所有套接字错误、可选的send/recv流量日志文件)输出更多可能会很快为解决方案指明方向。确保检查并输出所有套接字API调用中的任何错误。

您可以使用netstat检查侦听您的目标端口/地址的其他系统。

我看不出有什么明显的问题。

票数 1
EN

Stack Overflow用户

发布于 2010-10-28 08:53:59

我建议你这样做:

为了experiment

  • Make,
  • 从代码中删除所有getch()确保您的tcp服务器和tcp客户端应用程序都未运行
  • 在windows防火墙设置中删除应用程序的所有规则
  • 在CMD shell中运行以下命令-您需要使GREP可用: netstat -a -b | grep -e "27015“--after=1

如果此命令的输出不为空-您将看到一个应用程序的名称,该应用程序是问题的根源。否则,尝试通过运行服务器,然后运行客户端来重现问题。通过上面的netstat命令(或通过tcpview程序)监视服务器的状态。有趣的是,结果会是什么。

离题注意:您的断开序列不完整。谷歌搜索graceful disconnect。通常它看起来是这样的:

client发出关闭(sd_send)并等待来自服务器的剩余数据

发送服务器 if recv()==0 then {(剩余数据);发出关闭(Sd_send);关闭套接字}

客户端接收剩余数据;如果recv()为==0,则关闭

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4009587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档