D
D
Dmitry Richter2014-05-10 18:02:39
Work organization
Dmitry Richter, 2014-05-10 18:02:39

Sending data from server to client over 1 socket.C++

Good day. I need to make a chat in c ++, I did half the work and the client sends data to the server, everything is fine, I thought that to send data from the server to the client, just do everything back (that is, on the client, put listening to recv from the server, and on the server send) on the same socket, but something doesn’t work. What will the gurus tell? How best to do it? (TCP connection)
I wanted to ask if you still need to create another socket with the same parameters to send data to the client or what is the best way to do it?
here is the server code

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
         button3->Enabled = "true";
         timer1->Enabled = true;
         timer = "True";
         //--- INITIALIZATION -----------------------------------
         wVersionRequested = MAKEWORD(1, 1);
         err = WSAStartup(wVersionRequested, &wsaData);

         if (err != 0) {
           textBox1->Text = "WSAStartup error :" + System::Convert::ToString(WSAGetLastError());
           WSACleanup();
           timer = false;
         }


         //------------------------------------------------------



         //---- Build address structure to bind to socket.--------  
         memset(&channel, 0, sizeof(channel));// zerochannel 
         channel.sin_family = AF_INET;
         channel.sin_addr.s_addr = htonl(INADDR_ANY);
         channel.sin_port = htons(SERVER_PORT);
         //--------------------------------------------------------


         // ---- create SOCKET--------------------------------------
         s = socket(PF_INET,  SOCK_STREAM, IPPROTO_TCP);
         if (s < 0) {
           textBox1->Text = "socket error :" + System::Convert::ToString(WSAGetLastError());
           WSACleanup();
           timer = false;
         }

         setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
         //---------------------------------------------------------

         //---- BIND socket ----------------------------------------
         b = bind(s, (struct sockaddr *) &channel, sizeof(channel));
         if (b < 0) {
           textBox1->Text = "bind error :" + System::Convert::ToString(WSAGetLastError());
           WSACleanup();
           timer = false;
         }
         //----------------------------------------------------------

         //---- LISTEN socket ----------------------------------------
         l = listen(s, QUEUE_SIZE);                 // specify queue size 
         if (l < 0) {

           textBox1->Text = "listen error %ld" + System::Convert::ToString(WSAGetLastError());
           WSACleanup();
           timer = false;
         }

         //-----------------------------------------------------------


         //---- ACCEPT connection ------------------------------------

         sa = accept(s, 0, 0);                  // block for connection request  
         if (sa < 0) {

           textBox1->Text = "accept error " + System::Convert::ToString(WSAGetLastError());
           WSACleanup();
           timer = false;
         }
         else {

           textBox1->Text = "connection accepted";
         }
         //------------------------------------------------------------
      
         

  }
  private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
         timer = false;
         closesocket(s);
         closesocket(sa);
         WSACleanup();
         timer1->Enabled = FALSE;
  }
  private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
        // ---- RECV bytes --------------------------------------------

        
              unsigned long mode = 1;
              ioctlsocket(sa, FIONBIO, &mode);
              bytesRecv = recv(sa, recvbuf, 50, 0);
               err = WSAGetLastError();// 10057 = A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) 
               if (bytesRecv == 0 || bytesRecv == WSAECONNRESET) {

                 textBox1->Text = "Connection Closed.\n";
                 WSACleanup();
               }
               else{

                 textBox1->Text = gcnew String(recvbuf);

               }
          
  }
  private: System::Void button3_Click(System::Object^  sender, System::EventArgs^  e) {
         char buf[50] = "";
         int bytesSent;
         if (timer == true) {
           String ^ strT;
           strT = textBox2->Text;
           int TempNumOne = textBox2->Text->Length;
           for (int a = 0; a < TempNumOne; a++)
           {

             buf[a] = strT[a];

           }
         bytesSent = send(s, buf, 50, 0);
           
           textBox1->Text = "Sent:" + System::Convert::ToString(bytesSent);
           textBox1->Text = "Message :" + textBox2->Text; }
         }
  }

Answer the question

In order to leave comments, you need to log in

1 answer(s)
W
WhoMe, 2014-05-11
@WhoMe

Not a guru, but I'll put in my 5 cents.
General principle of operation (for blocking sockets)
Client (everything is simple here):
- Create a socket (ClientSocket)
- Connect to the server
- Write / read to / from ClientSocket
Server:
- Create a socket (ListenSocket)
- Call accept (the thread is blocked until it connects client or no error)
- Accept returns a socket (ClientSocket), it is associated with our connected client.
If we want to send/read data to/from this client, then we read/write from/to the ClientSocket.
- If we want to "accept" another client, then call Accept again
Again. If we have, say, 5 clients connected to the server. Then we get 6 sockets: 1 listening + 5 clients.
It will not be superfluous to note some features when working with blocking sockets.
Let's take the client side as an example.
You click a button in the interface, a function is called, for example button1_Click.
A socket is created and the connect function is called. At this point, the thread blocks until the socket is connected or an error occurs.
(Similarly with accept in the server part) That is, your program will visually "freeze". The interface will stop responding. The same goes for reading and writing.
The solution may be to create separate threads for working with sockets, or use multiplexed I / O.
According to your code:
1.
send(s, buf, 50, 0);
Sending data to the wrong socket. Must be in sa. (See sa = accept(s, 0, 0); // block for connection request)
2.

ioctlsocket(sa, FIONBIO, &mode);
bytesRecv = recv(sa, recvbuf, 50, 0);
err = WSAGetLastError();// 10057 = A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) 
if (bytesRecv == 0 || bytesRecv == WSAECONNRESET) {

Since you switched the socket to non-blocking mode, return zero is a normal situation here. Also note bytesRecv == WSAECONNRESET, the comparison is clearly against the wrong variable.
See also
habrahabr.ru/post/111357

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question