winsock 客户端和服务器通信

Posted

技术标签:

【中文标题】winsock 客户端和服务器通信【英文标题】:winsock client and server communication 【发布时间】:2010-11-22 15:31:42 【问题描述】:

抱歉,我知道过去一天我一直在发布与同一主题相关的主题,但我遇到了另一个问题。

服务器.cpp

/*Server */
#define _WIN32_WINNT 0x501
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
using namespace std;

const int winsock_version = 2;
#define PORT "3490"
#define MAX_NUM_CONNECTIONS 10

int main(void)

    WSADATA wsadata;

    if (WSAStartup(MAKEWORD(winsock_version,0),&wsadata) == 0)
        cout<<"-WSAStartup Initialized." << endl;

        struct addrinfo hints,*res;
        int sock_fd;

        memset(&hints,0,sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;

        if (getaddrinfo(NULL,PORT,&hints,&res) != 0)
            cout<<"-Call to getaddress was unsucceful." << endl;
        

        if( (sock_fd = socket(res->ai_family,res->ai_socktype,res->ai_protocol)) == -1)
            cout<<"-Unable to Create socket." << endl;
        

        if ( (bind(sock_fd, res->ai_addr, res->ai_addrlen)) != -1 )
            cout<<"-binding successful." << endl;
        

        if ( (listen(sock_fd,MAX_NUM_CONNECTIONS)) != -1)
            cout<<"-Listening for incoming connections." << endl;
        
        //-------------------------------------------------------------

        struct sockaddr_storage incming_info;
        socklen_t sin_size;
        sin_size = sizeof incming_info;

        int new_fd;

        new_fd = accept(sock_fd, (struct sockaddr*)&incming_info,&sin_size);
        if (new_fd == -1)
            cout<<"-Accepting error." << endl;
        
        if(new_fd == INVALID_SOCKET)
            cout<<"-INVALID SOCKET ERROR." << endl;
        
        //-------------------------------------------------------------

        cout<<"Connected?" << endl;
        char buffer[128];
        while(true)
            int ret_val;

            ret_val = recv(new_fd,buffer,sizeof(buffer),0);
            if(ret_val == -1)
                cout<<"Receiving Error." << endl;
                break;
            else if(ret_val == 0)
                cout<<"Connection has been closed!." << endl;
                break;
            else if(ret_val > 0)
                cout<<"Server: " << buffer<< endl;
            
        

        cout<<"-Closing connection" << endl;
        closesocket(new_fd);
    else
        cout<<"-WSAStartup Initialization failed." << endl;
        if(WSACleanup()!=0)
            cout<<"-WSACleanup Successful." << endl;
        else
            cout<<"-WSACleanup Failed." << endl;
        
    
    return 0;

client.cpp

/*client*/
#define _WIN32_WINNT 0x501
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
using namespace std;

#define PORT "3490"
#define SERVER "localhost"
const int winsockVersion = 2;


int main(void)

    WSADATA wsadata;
    if ( (WSAStartup(MAKEWORD(2,0),&wsadata)) == 0)
        cout<<"-WSAStartup Initialized." << endl;

        struct addrinfo hints, *res;
        int sockfd;

        memset(&hints,0,sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;

        if (getaddrinfo(SERVER,PORT,&hints,&res) != 0)
            cout<<"-getaddrinfo unsuccessful." << endl;
        

        if ( (sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol)) == -1 )
            cout<<"-Unable to create socket." << endl;
        

        if ( (connect(sockfd,res->ai_addr,res->ai_addrlen)) != -1 )
            cout<<"-Connection Established." << endl;
        

        cout<<"-Client connecting to: " << res->ai_addr << endl;

        while(true)
            char text_buff[128];
            cout<<"Enter text: ";
            cin>>text_buff;
            if( (send(sockfd,text_buff,sizeof(text_buff),0)) != -1 )
                cout<<"-text_buff sent!." << endl;
                break;
            
        closesocket(sockfd);

        

    else
        cout<<"-WSAStartup Initialization failed." << endl;
        if(WSACleanup()!=0)
            cout<<"-WSACleanup Successful." << endl;
        else
            cout<<"-WSACleanup Failed." << endl;
        
    

    return 0;

我可以很好地运行服务器和客户端,但是我只能从客户端发送一个单词(由于某种原因不能发送一个句子),该单词会在服务器控制台上打印出来,但一旦在服务器上打印出来控制台输出“接收错误”并关闭。

【问题讨论】:

【参考方案1】:

您不能假设对send() 的一次调用就足够了(recv() 也是如此)。您需要遍历数据,直到所有数据都已发送/接收。

此外,您很可能不希望总是发送 128 个字符,而应该只发送所需的长度(并且在消息中包含终止符或前缀长度)。

【讨论】:

嗯,是的,但是为什么在我能做到这一点之前连接就崩溃了。【参考方案2】:

两个问题 1. cin&gt;&gt;text_buff; 只读到第一个空格。您可以使用 std::string。 2.send(sockfd,text_buff,sizeof(text_buff),0)使用strlen(text_buff) + 1代替sizeof(text_buff)。 如果使用 std::string,请尝试

string line;  
send(sockfd, line.c_str(),line.length()+1,0)

【讨论】:

【参考方案3】:

尝试将使用 char text_buff 的输入替换为 std::string 和 std::getline。

while( true )

   std::string line;
   std::cout << "Enter text: ";
   std::getline( cin, line );
   if( send( sockfd, text_buff.c_str(), text_buff.size(), 0 ) ) != -1 )
   
      std::cout << "-text_buff sent!." << std::endl;
      break;
   
   closesocket( sockfd );

我不确定您在那里的循环,因为您似乎只是为了在第一次成功发送任何内容时退出而循环。

【讨论】:

以上是关于winsock 客户端和服务器通信的主要内容,如果未能解决你的问题,请参考以下文章

VB中使用winsock控件要实现网络通信怎么编程?服务端和客户端都必须各编个程序吗?

winsock 服务器同时发送和接收

Server->Client 之间的 C++ Winsock 通信,反之亦然

Winsock recv() 函数阻塞其他线程

WebSocket客户端和WinSock2服务器,可以吗?

TSINGSEE青犀视频编译Winsock2 websocket服务端连接异常断开问题排查