热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c/c++开发分享在VisualC++中接受来自客户端(套接字编程)的连接的问题

我在VisualC++中编写了一个简单的单线程客户端服务器应用程序。当我运行我的服务器时,我等待一段时间它接受来自客户端的一些请求。当我将客户端连接到服务器时。客户端上的日志消息报

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

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

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

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

服务器代码
#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include  #include  #include  #include  #include  #include  #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 socketn"); 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 objectn"); 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: %dn", 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: %dn", iRecvResult); getch(); // Echo the buffer back to the sender iSendResult = send(clientSocket, recvbuf, iRecvResult, 0); if (iSendResult == SOCKET_ERROR) { printf("send failed: %dn", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } printf("Bytes sent: %dn", iSendResult); } else if (iRecvResult == 0){ printf("Connection closing...n"); } else{ printf("recv failed: %dn", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } }while(iRecvResult > 0); getch(); return 0; } 
客户代码
 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include  #include  #include  #include  #include  #include  #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 getaddrInfon"); 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 socketn"); 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: %dn", WSAGetLastError()); closesocket(connectingSocket); WSACleanup(); return 1; } printf("Bytes Sent: %ldn", 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: %dn", 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: %dn", iResult); else if (iResult == 0) printf("Connection closedn"); else printf("recv failed: %dn", WSAGetLastError()); } while (iResult > 0); getch(); return 0; } 

    嗯…在修复了明显的语法错误( clientSocket = accept((listenSocket,NULL,NULL);的未匹配的开括号clientSocket = accept((listenSocket,NULL,NULL); )之后,它对我来说似乎运行得相当好。在服务器上我得到:

    收到的字节数:14
    发送的字节数:14
    连接关闭……

    在客户端:

    发送的字节数:14
    收到的字节数:14
    recv失败:10054

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

    编辑:我通过打开两个Windows SDK命令提示符窗口运行代码,在一个中运行server在另一个中运行client – 没有任何特别令人兴奋或不寻常的任何一个。

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

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

    我看不出任何明显的错误。

    我建议你做以下事情:

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

    Offtopic note:您的断开序列不完整。 谷歌graceful disconnect 。 通常它看起来像这样:

    [ client ]发出shutdown (sd_send)并等待来自服务器的剩余数据

    [ server ]如果recv ()== 0则{ send (剩余数据); 发出shutdown (sd_send); closesocket }

    [ 客户 ]收到剩余数据; 如果recv ()== 0则关闭

    在客户端中,您正在关闭发送连接:

     // 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: %dn", WSAGetLastError()); closesocket(connectingSocket); WSACleanup(); return 1; } 

    服务器检测到断开连接(recv返回0)并在不关闭其侧面连接的情况下完成,这就是您收到错误100054的原因。

      以上就是c/c++开发分享在Visual C ++中接受来自客户端(套接字编程)的连接的问题相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注(编程笔记)。


      推荐阅读
      • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
      • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
      • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
      • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
      • Java容器中的compareto方法排序原理解析
        本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
      • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
      • Java学习笔记之面向对象编程(OOP)
        本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
      • Java太阳系小游戏分析和源码详解
        本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
      • VScode格式化文档换行或不换行的设置方法
        本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
      • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
      • SpringBoot uri统一权限管理的实现方法及步骤详解
        本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
      • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
      • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
      • JavaSE笔试题-接口、抽象类、多态等问题解答
        本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
      • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
        本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
      author-avatar
      LookUp77
      这个家伙很懒,什么也没留下!
      PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
      Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有