简体   繁体   English

Winsock客户端和服务器通信

[英]winsock client and server communication

sorry I know I have been posting threads related to the same topic over throughout the past day but I've hit another issue. 抱歉,我知道我过去一整天都在发布与同一主题相关的主题,但是我遇到了另一个问题。

server.cpp server.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.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;
}

I can run the server and client fine, but I can only send one word (cant send a sentence for some reason) from the client which gets printed out on the server console but as soon as it is printed out on the server console it outputs "Receiving error" and closes. 我可以很好地运行服务器和客户端,但是我只能从客户端发送一个单词(出于某种原因不能发送句子),该单词会在服务器控制台上打印出来,但是一旦在服务器控制台上打印出来,它就会输出“接收错误”并关闭。

You can't assume that a single call to send() is enough (and the same for recv() ). 您不能假设对send()的单个调用就足够了(与recv()相同)。 You need to loop over the data until all data has been sent/received. 您需要遍历数据,直到发送/接收所有数据为止。

Also, you very probably don't want to always send 128 characters, instead you should just send the required length (and have either a terminator or a prefixed length in the message). 另外,您很可能不希望总是发送128个字符,而是应该发送所需的长度(并且在消息中具有终止符或带前缀的长度)。

Try replacing the input from using a char text_buff with a std::string and std::getline. 尝试使用带有std :: string和std :: getline的char text_buff替换输入。

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 );
}

I am not sure about your loop there as you seem to be looping just to exit the first time you successfully send anything. 我不确定您的循环在那里,因为您似乎只是在第一次成功发送任何内容时退出而循环。

Two issues 两个问题
1. cin>>text_buff; 1. cin>>text_buff; is reading only till the first space. 只读到第一个空格。 You can use std::string. 您可以使用std :: string。
2. send(sockfd,text_buff,sizeof(text_buff),0) use strlen(text_buff) + 1 instead of sizeof(text_buff) . 2. send(sockfd,text_buff,sizeof(text_buff),0)使用strlen(text_buff) + 1代替sizeof(text_buff)
If using std::string, then try 如果使用std :: string,请尝试

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM