Answer the question
In order to leave comments, you need to log in
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
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) {
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question