Why does string a return 'C' instead of "C:\Users\Desktop\Project phoneedge\ForMark\Top"?
When I tested it in a empty c++ project, and before I moved some of my code from ThreadFunction to StartButton it worked(The UI is suppose to update constantly but the socket recv() is cockblocking it causing it only update once so I moved the UI code to startbutton)
This is the server code, after start button is pressed, initiate the socket and there is a thread created to run the listen() accept() and recv(). The close button closes the socket and the thread.
Server Code(MFC project)
void CUIServerDlg::StartButton()
{
WSADATA Winsockdata;
int iTCPClientAdd = sizeof(TCPClientAdd);
WSAStartup(MAKEWORD(2, 2), &Winsockdata);
TCPServerAdd.sin_family = AF_INET;
TCPServerAdd.sin_addr.s_addr = inet_addr("127.0.0.1");
TCPServerAdd.sin_port = htons(8000);
TCPServersocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(TCPServersocket, (SOCKADDR*)&TCPServerAdd, sizeof(TCPServerAdd));
bRunning = true;
hthread = CreateThread(NULL, 0, ThreadFunction, this, 0, &ThreadID);
WaitForSingleObject(hthread, INFINITE);
funRunning = true;
while (funRunning == true) {
vector<string> caseOne;
/*string a;
char RecvBuffer[512];//this is the declaration in member class
int iRecvBuffer = strlen(RecvBuffer) + 1;*/
**a = RecvBuffer;**//a is a String, RecvBuffer is a path name like c:\user..
//Find files,This part of code is left out because it should not effect the question
//put the files found in a vector, then display it on a listbox
for (string fileVec : caseOne) {
CString fileunderPath;
string filevector1 = fileVec;
fileunderPath = filevector1.c_str();//conversion for AddString
list1.AddString(fileunderPath);
}
Sleep(1000);//The code updates every 1 second , when file names are modified is displays immediately.
}
}
I am suppose to change Sleep(1000) into WaitForSingleObject() to replace WM_Timer for the assignment but I don't know how since you need a handle, do I create another thread?
void CUIServerDlg::CloseButton()
{
bRunning = false;
funRunning = false;
WaitForSingleObject(hthread, INFINITE);
CloseHandle(hthread);
closesocket(TCPServersocket);
}
So I have never learned anything about socket and thread prior to this project, the idea of the code below is to use a thread to run a while loop to constantly check for new cilents to send things in, do make sure to correct me if the thought process is wrong.
DWORD WINAPI CUIServerDlg::ThreadFunction(LPVOID lpParam) {
CUIServerDlg* This = (CUIServerDlg*)lpParam;
while (This->bRunning == true) {
int iListen = listen(This->TCPServersocket, 10);
if (iListen == INVALID_SOCKET)
OutputDebugString(_T("FAIL LISTEN\n"));
This->sAccecpSocket = accept(This->TCPServersocket, (SOCKADDR*)&This->iTCPClientAdd, &This->iTCPClientAdd);
recv(This->sAccecpSocket, This->RecvBuffer, This->iRecvBuffer, 0);
}
return 0;
}
Client Code (Empty c++ project)
int main(){
string a = "C:\\Users\\Desktop\\Project phoneedge\\ForMark\\Top";
const char* SenderBuffer = a.c_str();
int iSenderBuffer = strlen(SenderBuffer) + 1;
WSAStartup(MAKEWORD(2, 2), &WinSockData);
TCPClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
TCPServerAdd.sin_family = AF_INET;
TCPServerAdd.sin_addr.s_addr = inet_addr("127.0.0.1");
TCPServerAdd.sin_port = htons(8000);
connect(TCPClientSocket,(SOCKADDR*)&TCPServerAdd,sizeof(TCPServerAdd));
send(TCPClientSocket, SenderBuffer, iSenderBuffer, 0);
closesocket(TCPClientSocket);
WSACleanup();
system("PAUSE");
return 0;
}
The TCP protocol passes the data by byte stream.
It means the client passes the data byte by byte rather than pass all the data at one time.
When you receive the data from the client. The passing procedure maybe not be finished.
So you need to check whether the data is finished passing after receiving some data by one recv call and then save the sub-data until receiving all the data.
Related
Recently my code meet some issue. My programme work as server and listen to ONE client to connect, then send some commands to my programme. Then I will handle this command and return the value to client side.
But now I got the issue accept() method will get 10093(WSANOTINITIALISED) error and seems accept() method didn't block there.
It is not always happened. I tested the programme. Sometimes it works very well. Client side connected to my programme and send first command. Then my programme handle the command and send back return value. Then stopped the connection(closesocket(sClient);). Then Client side connected to my programme again and send second command...While time to time it happened accept() get 10093(WSANOTINITIALISED) error and client side will fail to connect to my programme any more. and the while loop(while (true && !m_bExitThread)) also didn't block.
My questions are:
Why did it happen? did someone meet the same issue? I believe my code should be correct, otherwise why most of time it works well.
If this 10093 error comes, how should I handle it? Do I need to closesocket and wait for Client side connect again? or do I need to WSACleanup(); and try to start this socket Thread totally again?
Below is the code. it is a thread I start it when my programme start up and stop it when programme stopped.
UINT CMainFrame::RunSocketThread()
{
m_bExitThread = false;
WORD wSockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(wSockVersion, &wsaData) != 0) // Here always success, no problem
{
LOGL(ILoggingSink::LogLevel::Error, _T("WSAStartup error !"));
return 0;
}
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
LOGL(ILoggingSink::LogLevel::Error, _T("socket error !"));
return 0;
}
sockaddr_in stSocketAddr;
stSocketAddr.sin_family = AF_INET;
stSocketAddr.sin_port = htons(7700);
stSocketAddr.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(slisten, (LPSOCKADDR)&stSocketAddr, sizeof(stSocketAddr)) == SOCKET_ERROR)
{
LOGL(ILoggingSink::LogLevel::Error, _T("bind error !"));
return 0;
}
if (listen(slisten, 5) == SOCKET_ERROR)
{
LOGL(ILoggingSink::LogLevel::Error, _T("listen error !"));
return 0;
}
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[255];
while (true && !m_bExitThread)
{
// Waiting for connection
sClient = accept(slisten, (SOCKADDR*)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET) // Here I can get error code 10093(WSANOTINITIALISED)
{
LOGL(ILoggingSink::LogLevel::Error, _T("accept error %d!"), WSAGetLastError());
continue;
}
// revice data
int ret = recv(sClient, revData, 255, 0);
if (ret > 0)
{
revData[ret] = 0x00;
ParseJsonCommand(revData);
}
// send data
// Here I wait for programme finished handling the income command and return a value, otherwise just sleep and wait
while (CmdLineInfo::m_eReturn == ReturnTypeEnum::kNull)
{
Sleep(100);
}
const char* sendData;
CString strData;
strData = "{\"Command\":\"";
strData += CmdLineInfo::s_sLFODCommandName;
strData += "\", \"ReturnValue\":\"";
if(CmdLineInfo::m_eReturn == ReturnTypeEnum::kSuccess)
strData +="1\"} ";
else
strData += "0\"} ";
CStringA strAData(strData);
sendData = strAData;
send(sClient, sendData, strlen(sendData), 0);
closesocket(sClient);
}
closesocket(slisten);
WSACleanup();
return 0;
}
I am trying to write client server application using udp protocol, but I have problem with connection ending.
I open two sockets (one is a "server" and the other is a "client"), and while the server receiving from the client with async, the client send him one simple message that printed to the console.
After some sleep (to be sure the server will call again to recv) the client and server socket getting closed.
At this point I expected the recv will return -1 and the async will end.
But what actualy happen is that the recv stuck forever*.
If just before closing the socket I sending an empty package (sendToMakeExit variable set to true in the code), the recv return with that empty package, and only after next call it return -1, although the socket was closed in the first calling.
const bool sendToMakeExit = false;
const int port = 2000;
const auto addr = "127.0.0.1";
int serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons(port);
inet_pton(AF_INET, addr, &target.sin_addr);
bind(serverSocket, (sockaddr *) &target, sizeof(target));
auto readAsync = std::async(std::launch::async, [&serverSocket] {
const int MAX_READ = 4096;
char readBuf[MAX_READ];
ssize_t actualRead;
do {
actualRead = recv(serverSocket, readBuf, MAX_READ, 0);
if (actualRead > 0) {
cout << readBuf << endl;
}
} while (actualRead != -1);
});
int clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
connect(clientSocket, (sockaddr *) &target, sizeof(target));
this_thread::sleep_for(chrono::seconds(1));
send(clientSocket, "test", 5, 0);
this_thread::sleep_for(chrono::seconds(1));
close(clientSocket);
if (sendToMakeExit) {
sendto(serverSocket, nullptr, 0, 0, (sockaddr *) &target, sizeof(target));
}
close(serverSocket);
*If I run this code in debug and create new breakpoint when the recv is stuck surprisingly the recv return with -1.
How can I getting the recv will return -1 when I close the socket?
Closing a socket does not guarantee that any function call in another thread that is still using that socket immediately returns. If you have calls that wait for data to come in, like recv(), select(), poll(), you must send some data to the socket for these calls to return. You do that in your code, but you don't actually exit when a zero-length UDP packet is received: change the end of the while-loop to:
} while (actualRead > 0);
However, I would recommend having a flag variable that indicates whether the thread should continue running or not, like so:
volatile bool running = true;
auto readAsync = std::async(std::launch::async, [&serverSocket, &running] {
...
while (running) {
...recv()...
}
});
...
running = false;
sendto(serverSocket, ...);
readAsync.wait();
close(serverSocket);
Note that I added a line to wait for readAsync to finish before closing the socket, in order to prevent any accidents from happening: there is a small window where the socket is invalidated, but readAsync might still call recv() on it. If you have even more threads, it might also happen that you close the socket in this thread, another thread opens a new socket and gets the same filedescriptor number as the one you just closed, and then the readAsync thread would use the wrong socket.
I'm attempting to create a UDP client/server class that relies on IO completion ports using Winsock, but I haven't been able to get the GetQueuedCompletionStatus() function to return when new data is available. This is likely due to some misunderstanding on my part, but examples/documentation on IOCP with UDP instead of TCP are few and far between.
Here's the relevant bits of my server class, with error checking removed for brevity:
Server::Server()
{
m_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
}
void Server::StartReceiving()
{
StopReceiving();
m_iocp = CreateIoCompletionPort((HANDLE)m_receiveSocket, m_iocp, (DWORD)this, 0);
//WSAEVENT event = WSACreateEvent();
//WSAEventSelect(m_receiveSocket, event, FD_ACCEPT | FD_CLOSE);
// Start up worker thread for receiving data
m_receiveThread.reset(new std::thread(&Server::ReceiveWorkerThread, this));
}
void Server::Host(const std::string& port)
{
if (!m_initialized)
Initialize();
addrinfo hints = {};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
const char* portStr = port.empty() ? kDefaultPort.c_str() : port.c_str();
int result;
AddressInfo addressInfo = AddressInfo::Create(nullptr, portStr, &hints, result); // Calls getaddrinfo()
m_receiveSocket = WSASocket(addressInfo.GetFamily(), addressInfo.GetSocketType(), addressInfo.GetProtocol(), nullptr, 0, WSA_FLAG_OVERLAPPED);
// Bind receiving socket
result = bind(m_receiveSocket, addressInfo.GetSocketAddress(), addressInfo.GetAddressLength());
StartReceiving();
}
void Server::ReceiveWorkerThread()
{
SOCKADDR_IN senderAddr;
int senderAddrSize = sizeof(senderAddr);
DWORD bytesTransferred = 0;
OVERLAPPED* pOverlapped = nullptr;
WSABUF wsaBuf = { (ULONG)m_buffer.GetWriteBufferSize(), m_buffer.GetWriteBufferPointer() };
DWORD flags = 0;
DWORD bytesReceived;
int result = WSARecvFrom(m_receiveSocket, &wsaBuf, 1, &bytesReceived, &flags, (sockaddr*)&senderAddr, &senderAddrSize, pOverlapped, nullptr);
// Process packets until signaled to exit
while (true)
{
DWORD context = 0;
BOOL success = GetQueuedCompletionStatus(
m_iocp,
&bytesTransferred,
&context,
&pOverlapped,
INFINITE);
wsaBuf.len = (ULONG)m_buffer.GetWriteBufferSize();
wsaBuf.buf = m_buffer.GetWriteBufferPointer();
flags = 0;
result = WSARecvFrom(m_receiveSocket, &wsaBuf, 1, &bytesReceived, &flags, (sockaddr*)&senderAddr, &senderAddrSize, pOverlapped, nullptr);
// Code to process packet would go here
if (m_exiting.load() == true)
break; // Kill worker thread
}
}
When my client sends data to the server, the first WSARecvFrom picks up the data correctly but the server blocks on the call to GetQueuedCompletionStatus and never returns, even if more datagrams are sent. I've also tried putting the socket into non-blocking mode with WSAEventSelect (code for that is commented above), but it made no difference.
From reading this similar post it sounds like there needs to be at least one read on the socket to trigger IOCP, which is why I added the first call to WSARecvFrom outside the main loop. Hopefully I'm correct in assuming that the client code is irrelevant if the server receives the data without IOCP, so I haven't posted it.
I'm sure I'm doing something wrong, but I'm just not seeing it.
You need to check the result code from WSARecvFrom and call GetQueuedCompletionStatus only if the return code is ERROR_IO_PENDING- if it is not either the operation completed without blocking and you have the data, or there was an error, but in any of these cases it was not posted to the I/O completion port and thus it will never be picked up by GetQueuedCompletionStatusand the call will block.
And you should not do this in one thread. The common approach is to have a thread that only polls the I/O completion port and calls some callbacks on context objects to notify about incoming/outgoing data, and the sending receiving calls are called wherever needed.
Trying to write a client which will try to receive data till 3 seconds. I have implemented the connect method using select by below code.
//socket creation
m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
m_stAddress.sin_family = AF_INET;
m_stAddress.sin_addr.S_un.S_addr = inet_addr(pchIP);
m_stAddress.sin_port = htons(iPort);
m_stTimeout.tv_sec = SOCK_TIMEOUT_SECONDS;
m_stTimeout.tv_usec = 0;
//connecting to server
long iMode = 1;
int iResult = ioctlsocket(m_hSocket, FIONBIO, &iMode);
connect(m_hSocket, (struct sockaddr *)&m_stAddress, sizeof(m_stAddress));
long iMode = 0;
iResult = ioctlsocket(m_hSocket, FIONBIO, &iMode);
fd_set stWrite;
FD_ZERO(&stWrite);
FD_SET(m_hSocket, &stWrite);
iResult = select(0, NULL, &stWrite, NULL, &m_stTimeout);
if((iResult > 0) && (FD_ISSET(m_hSocket, &stWrite)))
return true;
But I cannot figure out what I am missing at receiving timeout with below code? It doesn't wait if the server connection got disconnected. It just returns instantly from select method.
Also how can I write a non blocking socket call with timeout for socket send.
long iMode = 1;
int iResult = ioctlsocket(m_hSocket, FIONBIO, &iMode);
fd_set stRead;
FD_ZERO(&stRead);
FD_SET(m_hSocket, &stRead);
int iRet = select(0, &stRead, NULL, NULL, &m_stTimeout);
if ((iRet > 0) && (FD_ISSET(m_hSocket, &stRead)))
{
while ((iBuffLen-1) > 0)
{
int iRcvLen = recv(m_hSocket, pchBuff, iBuffLen-1, 0);
if (iRcvLen == SOCKET_ERROR)
{
return false;
}
else if (iRcvLen == 0)
{
break;
}
pchBuff += iRcvLen;
iBuffLen -= iRcvLen;
}
}
The first parameter to select should not be 0.
Correct usage of select can be found here :
http://developerweb.net/viewtopic.php?id=2933
the first parameter should be the max value of your socket +1 and take interrupted system calls into account if it is non blocking:
/* Call select() */
do {
FD_ZERO(&readset);
FD_SET(socket_fd, &readset);
result = select(socket_fd + 1, &readset, NULL, NULL, NULL);
} while (result == -1 && errno == EINTR);
This is just example code you probably need the timeout parameter as well.
If you can get EINTR this will complicate your required logic, because if you get EINTR you have to do the same call again, but with the remaining time to wait for.
I think for non blocking mode one needs to check the recv() failure along with a timeout value. That mean first select() will return whether the socket is ready to receive data or not. If yes it will go forward else it will sleep until timeout elapses on the select() method call line. But if the receive fails due to some uncertain situations while inside read loop there we need to manually check for socket error and maximum timeout value. If the socket error continues and timeout elapses we need to break it.
I'm done with my receive timeout logic with non blocking mode.
Please correct me if I am wrong.
bool bReturn = true;
SetNonBlockingMode(true);
//check whether the socket is ready to receive
fd_set stRead;
FD_ZERO(&stRead);
FD_SET(m_hSocket, &stRead);
int iRet = select(0, &stRead, NULL, NULL, &m_stTimeout);
DWORD dwStartTime = GetTickCount();
DWORD dwCurrentTime = 0;
//if socket is not ready this line will be hit after 3 sec timeout and go to the end
//if it is ready control will go inside the read loop and reads data until data ends or
//socket error is getting triggered continuously for more than 3 secs.
if ((iRet > 0) && (FD_ISSET(m_hSocket, &stRead)))
{
while ((iBuffLen-1) > 0)
{
int iRcvLen = recv(m_hSocket, pchBuff, iBuffLen-1, 0);
dwCurrentTime = GetTickCount();
if ((iRcvLen == SOCKET_ERROR) && ((dwCurrentTime - dwStartTime) >= SOCK_TIMEOUT_SECONDS * 1000))
{
bReturn = false;
break;
}
else if (iRcvLen == 0)
{
break;
}
pchBuff += iRcvLen;
iBuffLen -= iRcvLen;
}
}
SetNonBlockingMode(false);
return bReturn;
I'm looking for an example of how to use libssh2 to setup ssh port forwarding. I've looked at the API, but there is very little in the way of documentation in the area of port forwarding.
For instance, when using PuTTY's plink there is the remote port to listen on, but also the local port that traffic should be sent to. Is it the developers responsibility to set this up? Can someone give an example of how to do this?
Also, an example where remote port is brought to a local port would be useful. Do I use libssh2_channel_direct_tcpip_ex()?
I'm willing to put up a bounty if need be to get a couple of working examples of this.
The key to making libssh2 port forwarding work was discovering that it basically just gives you the data that came in to that port. You have to actually send the data onto a local port that you open:
(Note, this code is not yet complete, there is no error checking, and the thread yielding isn't correct, but it gives a general outline of how to accomplish this.)
void reverse_port_forward(CMainDlg* dlg, addrinfo * hubaddr, std::string username, std::string password, int port)
{
int iretval;
unsigned long mode = 1;
int last_socket_err = 0;
int other_port = 0;
fd_set read_set, write_set;
SOCKET sshsock = socket(AF_INET, SOCK_STREAM, 0);
iretval = connect(sshsock, hubaddr->ai_addr, hubaddr->ai_addrlen);
if (iretval != 0)
::PostQuitMessage(0);
LIBSSH2_SESSION * session = NULL;
session = libssh2_session_init();
iretval = libssh2_session_startup(session, sshsock);
if (iretval)
::PostQuitMessage(0);
iretval = libssh2_userauth_password(session, username.c_str(), password.c_str());
dlg->m_track_status(dlg, 1, 0, "Authorized");
LIBSSH2_LISTENER* listener = NULL;
listener = libssh2_channel_forward_listen_ex(session, "127.0.0.1", port, &other_port, 1);
if (!listener)
::PostQuitMessage(0);
LIBSSH2_CHANNEL* channel = NULL;
ioctlsocket(sshsock, FIONBIO, &mode);
libssh2_session_set_blocking(session, 0); // non-blocking
int err = LIBSSH2_ERROR_EAGAIN;
while (err == LIBSSH2_ERROR_EAGAIN)
{
channel = libssh2_channel_forward_accept(listener);
if (channel) break;
err = libssh2_session_last_errno(session);
boost::this_thread::yield();
}
if (channel)
{
char buf[MAX_BUF_LEN];
char* chunk;
long bytes_read = 0;
long bytes_written = 0;
int total_set = 0;
timeval wait;
wait.tv_sec = 0;
wait.tv_usec = 2000;
sockaddr_in localhost;
localhost.sin_family = AF_INET;
localhost.sin_addr.s_addr = inet_addr("127.0.0.1");
localhost.sin_port = htons(5900);
SOCKET local_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ioctlsocket(local_sock, FIONBIO, &mode);
iretval = connect(local_sock, (sockaddr*) &localhost, sizeof(localhost) );
if (iretval == SOCKET_ERROR)
iretval = WSAGetLastError();
while (1)
{
bytes_read = libssh2_channel_read(channel, buf, MAX_BUF_LEN);
if (bytes_read >= 0){
FD_ZERO(&read_set);
FD_ZERO(&write_set);
FD_SET(local_sock, &write_set);
// wait until the socket can be written to
while (select(0, &read_set, &write_set, NULL, &wait) < 1)
boost::this_thread::yield();
if (FD_ISSET(local_sock, &write_set))
{
FD_CLR(local_sock, &write_set);
chunk = buf;
// everything may not get written in this call because we're non blocking. So
// keep writing more data until we've emptied the buffer pointer.
while ((bytes_written = send(local_sock, chunk, bytes_read, 0)) < bytes_read)
{
// if it couldn't write anything because the buffer is full, bytes_written
// will be negative which won't help our pointer math much
if (bytes_written > 0)
{
chunk = buf + bytes_written;
bytes_read -= bytes_written;
if (bytes_read == 0)
break;
}
FD_ZERO(&read_set);
FD_ZERO(&write_set);
FD_SET(local_sock, &write_set);
// wait until the socket can be written to
while (select(0, &read_set, &write_set, NULL, &wait) < 1)
boost::this_thread::yield();
}
}
}
FD_ZERO(&read_set);
FD_ZERO(&write_set);
FD_SET(local_sock, &read_set);
select(0, &read_set, &write_set, NULL, &wait);
if (FD_ISSET(local_sock, &read_set))
{
FD_CLR(local_sock, &read_set);
bytes_read = recv(local_sock, buf, MAX_BUF_LEN, 0);
if (bytes_read >= 0)
{
while ((bytes_written = libssh2_channel_write_ex(channel, 0, buf, bytes_read)) == LIBSSH2_ERROR_EAGAIN)
boost::this_thread::yield();
}
}
boost::this_thread::yield();
} // while
} // if channel
}
P.S. To make this work requires the latest SVN builds of libssh2. There were bugs in prior versions that kept port forwarding from being usable.
The libssh2 source code includes since a few years a direct_tcpip.c example which demonstrates how to create direct-tcpip SSH channels, and since last week a forward-tcpip.c example which demonstrates how to create forward-tcpip SSH channels.
direct-tcpip is what ssh -L uses, and forward-tcpip is what ssh -R uses.
It is always the responsibility of libssh2 users to deal with the actual data. libssh2 takes care of SSH channels and nothing else. You can benefit significantly from studying the SSH RFCs, in particular RFC 4254, to find more about what exactly each channel type promises you, and thus what you can expect from libssh2.