I'm trying to implement my own server and client side which uses sockets to send and receive data. But i got some problem with realization of multi-threading.
My server.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <thread>
using namespace std;
void connection_handler(int socket) {
char client_message[256];
memset(&client_message, 0, 256);
size_t message_size = 0;
while ((message_size = recv(socket, client_message, sizeof(client_message) - 1, 0)) > 0) {
client_message[message_size] = '\0';
cout << "[Server] Client message accepted" << endl;
cout << "[Server] Client message: " << client_message << endl;
if (write(socket, client_message, message_size) == -1) {
cout << "[Client] Message sending failed" << endl;
return;
}
cout << "[Server] Message sent to client" << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
memset(&client_message, 0, 256);
}
}
int main() {
unsigned short int PORT = 8080;
int listener, client_socket;
socklen_t client_len;
struct sockaddr_in server_address{};
memset(&server_address, 0, sizeof(server_address));
listener = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
if (inet_aton("127.0.0.1", &server_address.sin_addr) == 0) {
cout << "[Server] Invalid IP address" << endl;
return -1;
}
if (bind(listener, (struct sockaddr*) &server_address, sizeof(server_address)) == -1) {
cout << "[Server] Binding failed" << endl;
return -1;
}
cout << "[Server] All setting are done" << endl;
cout << "[Server] Server enabled" << endl;
if (listen(listener, 100) == -1) {
cout << "[Server] Listening failed" << endl;
return -1;
}
cout << "[Server] Waiting for connection..." << endl;
for (; ;) {
client_socket = accept(listener, (struct sockaddr*) &server_address, &client_len);
cout << "[Server] Connection accepted" << endl << endl;
cout << "----------------------------" << endl << endl;
int new_socket = client_socket;
thread handling_thread(connection_handler, new_socket);
handling_thread.detach();
}
}
My client.cpp:
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
int main() {
unsigned short int PORT = 8080;
int sockfd;
char buffer[256] = {0};
struct sockaddr_in server_address{};
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&server_address, '0', sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.s_addr = INADDR_ANY;
if (connect(sockfd, (struct sockaddr*) &server_address, sizeof(server_address)) < 0) {
cout << "[Client] Connection failed" << endl;
return -1;
}
cout << "[Client] All setting are done" << endl;
cout << "[Client] Succefully connected to server" << endl << endl;
cout << "----------------------------" << endl << endl;
while (true) {
string client_request;
cout << "[Client] Enter a message: ";
getline(cin, client_request);
if (client_request == "-1") {
write(sockfd, client_request.c_str(), client_request.size());
close(sockfd);
cout << endl << "[Client] Client exited" << endl;
return 0;
}
if (write(sockfd, client_request.c_str(), client_request.size()) == -1) {
cout << "[Client] Message sending failed" << endl;
}
cout << "[Client] Message sent to server" << endl;
memset(&buffer, 0, 256);
read(sockfd, buffer, 256);
cout << "[Client] Server message: " << buffer << endl << endl;
cout << "============================" << endl << endl;
cout.flush();
}
}
It's perfectly working until i create one more connection to server and after that second client cans send and receive data, but first one at this time becomes not working.
I compiled my program like this: g++ server.cpp -lpthread -o server -std=c++11 And then in other console tab run my compiled client.cpp: ./client.
To check multi-threading working i run client one more time (in other tab again) and trying send requests in two tabs at the same time.
I want to realize multi-threading in my program. How can i do this?
UPD: I'm using Linux
UPD2: Problem solved. Fixed code there.
int new_socket = client_socket;
thread handling_thread(connection_handler, &new_socket);
handling_thread.detach();
}
This initializes new_socket, which gets declared in local scope inside this for loop, then passes the pointer to this new_socket to a new thread that gets started, and detached. Immediately after that, this for loop iteration ends, which destroys the new_socket object, before starting the next iteration of this loop.
Meanwhile, the execution thread repeatedly attempts to dereference the int * it receives, which now points to a destroyed object. This results in undefined behavior, and the likely reason your program is "not working".
The most simple solution is to create the int socket value in dynamic scope, using new, and then pass the pointer to this newed socket value to the execution thread. The execution thread will, of course, be responsible for retrieving the socket value, then properly deleteing it, to avoid leaking memory.
This should be sufficient for this simple program. More complicated programs will likely require slightly more sophisticated socket and dynamic scoping handling logic, for reliability.
Related
The problem seems to be in step 8. I am trying to use a while loop on the recv() function that I thought would allow me to keep appending to the RecvBuffer, but instead it just stalls and the program doesn't do anything. I am pretty sure I am missing something that would enable me to take multiple lines of input from a connected session, say, via netcat.exe for example. Any suggestions would be very welcome.
UPDATE: I made some edits, and I can now continue to input from the client connection, and these get sent, but I get weird outputs from the previous input and clearing the buffer doesn't seem to work.
The out put I get in the Server when I input "something goes here" from
cout << "Receive success: " << RecvBuffer << " ----> end of input"<<endl;
is this:
Receive success: g goes h ----> end of input
Receive success: ere
es h ----> end of input
I'm not sure why the above occurs
#include <iostream>
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <Tchar.h>
#pragma warning(suppress : 4996)
using namespace std;
int main()
{
cout << "TCP SERVER" << endl;
//LOCAL VARIABLES
WSADATA Winsockdata;
int iWsaStartUp;
int iWsaCleanUp;
SOCKET TCPServerSocket;
int iCloseSocket;
struct sockaddr_in TCPServerAdd; //This is the structure
struct sockaddr_in TCPClientAdd;
int iTCPClientAdd = sizeof(TCPClientAdd);
int iBind;
int iListen;
SOCKET sAcceptSocket;
int iSend;
char SenderBuffer[512] = "Hello from server!";
int iSenderBuffer = strlen(SenderBuffer);
int iRecv;
char RecvBuffer[512] = "Input: ";
int iRecvBuffer = strlen(RecvBuffer) + 1;
int newiRecv;
char newRecvBuffer[512];
int newiRecvBuffer = strlen(newRecvBuffer) + 1;
//STEP 1: WSAStasrtup Function - initiates use of the Winsock DLL by a process
//See the MSDN for a great guite for this and ALL of the processes here-https://learn.microsoft.com/en-gb/windows/win32/winsock/initializing-winsock
//and https://learn.microsoft.com/en-gb/windows/win32/winsock/creating-a-basic-winsock-application
iWsaStartUp = WSAStartup(MAKEWORD(2, 2), &Winsockdata); //more info-https://stackoverflow.com/questions/24131843/what-is-makeword-used-for
if (iWsaStartUp != 0) {
cout << "WSAStartup FAILED" << endl;
}
else {
cout << "WSAStartup Success" << endl;
}
//STEP 2 - FILL THE STRUCTURE
TCPServerAdd.sin_family = AF_INET;
InetPton(AF_INET, _T("127.0.0.1"), &TCPServerAdd.sin_addr.s_addr);
//TCPServerAdd.sin_addr.s_addr = inet_addr("127.0.0.1"); <------- this is now depreciated, so see the above line of code
TCPServerAdd.sin_port = htons(8000);
//STEP 3: Create socket
TCPServerSocket = socket(AF_INET, SOCK_STREAM,0);
if (TCPServerSocket == INVALID_SOCKET) {
cout << "TCP Server socket gailed " << WSAGetLastError() << endl;
}
else {
cout << "TCP Server socket creation success" << endl;
}
//STEP 4: Bind
iBind = bind(TCPServerSocket, (SOCKADDR*)&TCPServerAdd, sizeof(TCPServerAdd));
if (iBind == SOCKET_ERROR) {
cout << "bind failed with " << WSAGetLastError() << endl;
}
else {
cout << "bind success" << endl;
}
//STEP 5: listen
iListen = listen(TCPServerSocket, SOMAXCONN);
if (iListen == SOCKET_ERROR) {
cout << "Listen function failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Listen fucntiuon success" << endl;
}
//STEP 6: Accept
sAcceptSocket = accept(TCPServerSocket, (SOCKADDR*)&TCPClientAdd, &iTCPClientAdd);
if (sAcceptSocket == INVALID_SOCKET)
{
cout << "accept failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Accept success" << endl;
}
//STEP 7: send
iSend = send(sAcceptSocket, SenderBuffer, iSenderBuffer, 0);
if (iSend == SOCKET_ERROR)
{
cout << "send failed with " << WSAGetLastError() << endl;
}
else
{
cout << "send success" << endl;
}
//STEP 8: recv
while (1) {
iRecv = recv(sAcceptSocket, RecvBuffer, iRecvBuffer, 0);
if (iRecv == SOCKET_ERROR)
{
cout << "receive failed with " << WSAGetLastError() << endl;
}
else
{
cout << "Receive success: " << RecvBuffer << " ----> end of input"<<endl;
}
char txbuf[512];
strcpy_s(txbuf, "you said: ");
strcat_s(txbuf, RecvBuffer);
send(sAcceptSocket, txbuf, strlen(txbuf) + 1, 0);
}
}
I was not able to find what I was doing wrong on the internet.
My problem is that, recvfrom() function seems to remember the last value instead of making new calls and getting my buffer updated.
I've created the same code logic with Python and it works just find but I can't find a way to do the same in C++.
So that's my code :
#define _WINSOCKAPI_
#include <windows.h>
#include <winsock2.h>
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <time.h>
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
int main()
{
cout << "\t\t--------------UDP Server ---------------" << endl;
cout << endl;
WSADATA WinSockData;
int iWsaStartup, iWsaCleanup;
SOCKET UDPSocketServer;
struct sockaddr_in UDPClient;
char Buffer[200];
int iBind, iReceiveFrom;
int iUDPClientLen = sizeof(UDPClient);
int iCloseSocket;
int response, offset;
ULONG cmd = 0;
iWsaStartup = WSAStartup(MAKEWORD(2, 2), &WinSockData);
if (iWsaStartup != 0) {
cout << "WSAStartup Failed" << endl;
}
cout << "WSAStartup Success" << endl;
//Setting Socket connexion information
UDPClient.sin_family = AF_INET;
UDPClient.sin_addr.s_addr = htons(INADDR_ANY);
UDPClient.sin_port = htons(40100);
//Informations to send to this address
const char* msg = "///";
size_t msg_length = sizeof(msg) - 1;
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_addr.s_addr = inet_addr("192.128.20.65");
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(40100);
//Create Socket
UDPSocketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (UDPSocketServer == INVALID_SOCKET) {
cout << "Socket creation failed with error : " << WSAGetLastError() << endl;
WSACleanup();
exit(0);
}
cout << "Socket creation success" << endl;
//Binding Socket to INADDR_ANY 0.0.0.0:40100
iBind = bind(UDPSocketServer, (SOCKADDR*)&UDPClient, sizeof(UDPClient));
if (iBind == SOCKET_ERROR) {
cout << "Binding failed with error : " << WSAGetLastError() << endl;
closesocket(UDPSocketServer);
WSACleanup();
exit(0);
}
cout << "Binding success" << endl;
//Make sure the socket is blocking
if (ioctlsocket(UDPSocketServer, FIONBIO, &cmd) == SOCKET_ERROR) {
cout << "ioctlsocket failed with error : " << WSAGetLastError() << endl;
}
else
cout << "ioctlsocket success : " << cmd << endl; //Return 0 because it is set for Blocking
//Send information to 192.128.20.65:40100
response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
if (response == SOCKET_ERROR) {
cout << "Send failed with error : " << WSAGetLastError() << endl;
}
cout << "Send success : " << response << endl;
//Wait 4 seconds
Sleep(4000);
//Send information to 192.128.20.65:40100
response = sendto(UDPSocketServer, reinterpret_cast<const char*>(msg), msg_length, 0, (sockaddr*)&myaddr, sizeof(myaddr));
if (response == SOCKET_ERROR) {
cout << "Send failed with error : " << WSAGetLastError() << endl;
}
cout << "Send success : " << response << endl;
while (1) {
//Capture receive data from any address on port 40100
//This is supose to be a blocking function but it never block after the first return call
iReceiveFrom = recvfrom(UDPSocketServer, Buffer, sizeof(Buffer) + 1, MSG_PEEK, (SOCKADDR*)&UDPClient, &iUDPClientLen);
if (iReceiveFrom == SOCKET_ERROR) {
cout << "Receive failed with error : " << WSAGetLastError() << endl;
}
else if (iReceiveFrom != 0) {
Buffer[iReceiveFrom] = '\0'; //Add end of line to Buffer
//printf("%.*s\n", iReceiveFrom, Buffer);
cout << "Receive success : " << Buffer << endl;
}
}
iCloseSocket = closesocket(UDPSocketServer);
iWsaCleanup = WSACleanup();
if (iWsaCleanup == SOCKET_ERROR) {
cout << "WSA Cleanup failed with error : " << WSAGetLastError() << endl;
}
cout << "WSA Cleanup success" << endl;
system("PAUSE");
return 0;
}
I've created a UDP C++ socket that binds itself to 0.0.0.0:40100 and listens to that port using the function recvfrom().
The problem is that my recvfrom() function seems to never update or wait for new data. It just sends over the same old data without waiting.
I've tried to add some code that will change all the value of the buffer, but when recvfrom() is called the value recieved is the same as the old one.
From what I've read, recvfrom() function is supposed to be a blocking function, but in my case, it doesn't seems to work.
I've made sure the function was blocking by looking at ioctlsocket() function response; it's set to 0, so it's supposed to block.
I've also tried to create a new socket for my sendTo() function and I got the same result.
Finally, I've also tried to remove the sendTo() functions, but like my code in Python, no data seems to comeback from the socket if I don't send the string in the first place. (Wireshark shows that there's data that is sent to this port at all the time. Without this initialization, I can't get anything to print on my socket).
I find it strange that data is recieved on a certain port on my computer but when bind to that port I can't see this data before sending data to the address that send it in the first place. So I think the problem might happens between the sendTo() call and the recvfrom().
Using MSG_PEEK with recvfrom doesn't remove the data from the incoming data queue, it's still there the next time you call recvfrom.
I have finished my c++ tutorial and went to winsock, but still a bit new to the subject. I made a client code that tried to connect to a website using port 80 (http) but whenever i run it i get an error code 10049 and it doesn't connect to the server. Here is the code..
Defenitions.h:
#include <iostream>
#include <winsock2.h>
using namespace std;
//Prototypes:
WORD version = MAKEWORD(2, 2);
WSADATA info;
SOCKET hSocket;
USHORT port;
sockaddr_in hSockAddr;
char website[50];
void initWSA();
void createSocket();
hostent* websiteInfo;
void getPort();
void connectSocket();
void cleanUp();
//Functions:
void initWSA(){
if(WSAStartup(version, &info) == 0){
cout << "WinSock initialization successful!" << endl;
}else{
cout << "WinSock initialization failed!" << endl;
}
}
void createSocket(){
hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(hSocket != INVALID_SOCKET){
cout << "Socket Creation Successful!" << endl;
}else{
cout << "Socket Creation Failed!" << endl;
}
}
void getPort(){
cout << "Enter the port number to connect to:" << endl;
}
void connectSocket(){
if(connect(hSocket, (SOCKADDR*)&hSockAddr, sizeof(hSockAddr)) == 0){
cout << "Connection to server successful!" << endl;
}else{
cout << "Connection to server failed! error code: " << WSAGetLastError() << endl;
}
}
void cleanUp(){
if(closesocket(hSocket) == 0){
cout << "Socket Closure Successful!" << endl;
}else{
cout << "Socket Closure Failed!" << endl;
}
if(WSACleanup() == 0){
cout << "WinSock cleanup successful!\a" << endl;
}else{
cout << "WinSock cleanup failed!\a" << endl;
}
}
main.cpp:
#include "Definitions.h"
int main(int argc, char *argv[]){
initWSA();
createSocket();
cout << "IP Address of: " << "www.google.com" << " is: "<< gethostbyname("www.google.com") << endl;
getPort();
cin >> port;
hSockAddr.sin_family = AF_INET;
hSockAddr.sin_port = htons(port);
hSockAddr.sin_addr.S_un.S_addr = inet_addr("www.google.com");
connectSocket();
cleanUp();
return 0;
}
This is always what i get:
Any suggestions?
The problem is with how you convert host address to ip,
inet_addr is for ip addresses:
The inet_addr function converts a string containing an IPv4 dotted-decimal address into a proper address for the IN_ADDR structure.
instead of:
hSockAddr.sin_addr.S_un.S_addr = inet_addr("www.google.com");
use:
struct hostent *he = gethostbyname("www.google.com");
memcpy(&hSockAddr.sin_addr, he->h_addr_list[0], he->h_length);
// Or:
//hSockAddr.sin_addr.s_addr = ((in_addr *)(he->h_addr))->s_addr;
see here: converting host to ip by sockaddr_in gethostname etc
[edit]
As Remy Lebeau has written in comment, gethostbyname is depracated and getaddrinfo should be used instead, below is sample code using getaddrinfo:
// Resolve host name
struct addrinfo hints, *servinfo, *p;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int rv;
std::string str_port = std::to_string(port);
if ((rv = getaddrinfo("www.google.com", str_port.c_str(), &hints, &servinfo)) != 0) {
std::cerr << "getaddrinfo: " << rv << ": " << gai_strerrorA(rv) << std::endl;
return 1;
}
// Loop over all returnd addresses, first one that works is the one we want to use
for (p = servinfo; p != NULL; p = p->ai_next) {
createSocket();
if (connect(hSocket, p->ai_addr, p->ai_addrlen) == 0) {
cout << "Connection to server successful!" << endl;
break;
}
else {
cout << "Connection to server failed! error code: " << WSAGetLastError() << endl;
closesocket(hSocket);
}
}
freeaddrinfo(servinfo);
See Windows Sockets Error Codes, in this case:
WSAEADDRNOTAVAIL
10049
Cannot assign requested address.
The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer (for example, address or port 0).
Did you see your IP address output? I think it's not what you want.
I think you should see this example in order to get the IP address:
Winsock Programmer’s FAQ
Examples: Get the Local IP Address(es)
I found some code in the internet with some basics about creating an TCP/IP server in C++.
I took this code, added some libraries and some lines of code. The result is, that I am able to compile and run the code/server in Qt Creator on Windows as a console program. Nevertheless I am not able to connect to the server because it just runs through the code without waiting and accepting a connection from an TCP client.
This is the code:
EDIT: Code is updated and it's now working. Test against == -1 is the solution.
#define PORT 2000
#define MAX_QUEUE 5
#define BUF_SIZE 1024
int main(int argc, char* const argv[])
{
cout << "Hello World!" << endl;
WSADATA wsaData;
int wsaret = WSAStartup(MAKEWORD( 4, 4 ), &wsaData);
cout << "wsaret: " << wsaret << endl;
cout << "Start TCP/IP Server" << endl;
/* file descriptors for sockets */
SOCKET sock_1, sock_2; //switched from in to SOCKET //unsigned int sock_1, sock_2;
int rec_value, length;
char buf[BUF_SIZE];
//struct sockaddr_in server;
struct sockaddr_in server;
/* create stream socket in internet domain*/
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//if(sock_1 < 0)
if(sock_1 == -1)
{
cout << "socket: " << WSAGetLastError() << endl; //instead of //cout << "socket: " << strerror(errno) << endl; //cout << "socket wsaret: " << wsaret << endl;
exit(1);
}
/* build address in internet domain */
server.sin_family = AF_INET;
/* everyone is allowed to connet to server */
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129");
server.sin_port = htons(2000); //server.sin_port = PORT; //Port: 2000
/* bind socket */
//if(bind(sock_1, (struct sockaddr *)&server, sizeof(server)));
int bindreturn = (bind(sock_1, (struct sockaddr *)&server, sizeof(server)));
if(bindreturn == -1)
{
cout << "bind: " << WSAGetLastError() << endl; //instead of //cout << "bind: " << strerror(errno) << endl; //cout << "bind wsaret: " << wsaret << endl;
exit(1);
}
listen(sock_1,MAX_QUEUE);
/* start accepting connection */
sock_2 = accept(sock_1,0,0);
if(sock_2 < 0)
{
cout << "accept: " << WSAGetLastError() << endl;
exit(1);
}
/* read from sock_2 */
while(rec_value=recv(sock_2,buf,BUF_SIZE,0))
{
if(rec_value < 0)
{
cout << "recv: " << WSAGetLastError() << endl;
exit(1);
}
else
{
cout << "else" << endl;
send(sock_2,"1,2,3",strlen("1,2,3"),0);
}
}
cout << "Ending connection" << endl;
closesocket(sock_1);
closesocket(sock_2);
cout << "End TCP/IP Server" << endl;
WSACleanup();
return 0;
}
The console shows the following after/during running the program in one or less seconds:
Hello World!
wsaret: 0
Start TCP/IP Server
bind: 0
What can I do, that the server waits for an connection partner?
Thanks in advance.
Regards
matl
Edit: Added a few lines of code at the beginning, which I forgot before.
Edit: Code update
Edit: Code update
I'm going to comment in detail on the original code you posted.
cout << "Start TCP/IP Server" << endl;
//int sock_1,sock_2; /* file descriptors for sockets */
int sock_1, sock_2;
int rec_value, length;
char buf[BUF_SIZE];
//struct sockaddr_in server;
sockaddr_in server;
/* create stream socket in internet domain*/
sock_1 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//0);
Missing test here. You must test the result for -1 along these lines:
if (sock_1 == -1)
{
cout << "socket creation error: " << WSAGetLastError() << endl;
exit(1); // or some other measure to prevent continuation
}
Back to your code:
/* build address in internet domain */
server.sin_family = AF_INET;
/* everyone is allowed to connet to server */
server.sin_addr.s_addr = INADDR_ANY; //inet_addr("192.168.145.129");
server.sin_port = PORT; //Port: 2000
That should be
server.sin_port = htons(PORT);
Back to your code:
/* bind socket */
int bindreturn = bind(sock_1, (struct sockaddr *)&server, sizeof(server));
cout << "bindreturn: " << bindreturn << endl;
Inadequate. Here again you need to test for -1, and print WSAGetLastError() and exit if you got it.
listen(sock_1,MAX_QUEUE);
Untested. Here again you need to test for -1 etc.
/* start accepting connection */
//system("pause");
sock_2 =accept(sock_1,0,0);
//system("pause");
cout << "acceptreturn: " << sock_2 << endl;
Inadequate again, see above.
/* read from sock_2 */
while(rec_value=recv(sock_2,buf,BUF_SIZE,0))
{
if(rec_value<0)
{
cout << "error: " << rec_value << endl;
exit(1);
}
Test is incorrect. A system call indicates error by returning exactly -1, not just any value < 0. A socket FD for example returned by socket() or accept() can be negative, or any value other than -1.
else
{
cout << "else" << endl;
send(sock_2,"1,2,3",strlen("1,2,3"),0);
}
}
closesocket(sock_1);
closesocket(sock_2);
cout << "End TCP/IP Server" << endl;
return 0;
It is apparent from the closesocket() calls that you're using Winsock, in which case both WSAStart() and WSACleanup() are missing.
How is PORT defined?
You should use:
server.sin_port = htons(PORT); //Port: 2000
Is your IP-address correct?
All your calls are receiving SOCKET_ERROR (-1), so you should check lasterror to get more information.
Not sure (on Windows here), but shouldn't those be unsigned int's?
int sock_1, sock_2;
Update:
Ok, you seem to be using Qt on Windows.
For Qt, you might as well use the Qt libraries.
On Windows in general, you could use the free MS Visual Studio.
You also need to call WSAStartup() like this:
WSADATA wsaData;
int wsaret = WSAStartup(MAKEWORD( 4, 4 ), &wsaData);
// check wsaret
// more code here
WSACleanup();
Also use SOCKET:
SOCKET sock_1, sock_2;
Check the errorcodes with WSAGetLastError().
I am learning socket programming for use in an upcoming project, and I have researched the issue pretty extensively. Basically, all this program needs to is on a client computer (locally, i.e. my computer) needs to connect to a remote server and send a command (which it has done, I have gotten it to read back Apache server stats to me).
What is happening is this: I believe I have the socket set right, but the server receives random garbage buffers (one of which consisted of " '>Z"). I have tried various socket settings, different bindings, etc.
I have in the process of starting it will initialize winsock, create a socket, bind the network, and then do a listen loop and while(1) recv data.
I have yet to get the server (on a remote computer, hosted at a datacenter) to output the message. This is my only goal for the time being. I appreciate everyone's help in advance, and the code is before (this is the entire code, sorry for the length).
Client Code:
char *host = "127.0.0.1";
SOCKET clientsock;
struct sockaddr_in server_address;
struct hostent *host_info;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != -1) {
cout << "WINSOCK2 Initialized" << endl;
if((clientsock = socket(AF_INET, SOCK_STREAM, 0)) != SOCKET_ERROR) {
cout << "Socket Created" << endl;
char opt[2];
opt[0] = 0;
opt[1] = 1;
//setsockopt(clientsock, SOL_SOCKET, SO_BROADCAST, opt, sizeof(opt));
host_info = gethostbyname(host);
server_address.sin_family = AF_INET;
server_address.sin_addr = *((struct in_addr *)host_info->h_addr);
server_address.sin_port = htons(80);
if(connect(clientsock, (struct sockaddr *)&server_address, sizeof(struct sockaddr)) == 0) {
cout << "Connected to host" << endl;
char COMMAND[22] = "SVR --WINSOCK-VERIFY\0";
if(send(clientsock, COMMAND, sizeof(COMMAND), 0)) {
cout << "Command Sent" << endl;
closesocket(clientsock);
}
else {
cout << "ERROR - Could not send command. " << "Error: " << WSAGetLastError() << endl;
closesocket(clientsock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not connect to host. " << "Error: " << WSAGetLastError() << endl;
closesocket(clientsock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not create the socket. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
}
else {
cout << "ERROR - Could not initialize WINSOCK2. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
Server Code:
SOCKET serversock;
char *server = "127.0.0.1";
//char *server = "50.31.1.180";
struct sockaddr_in server_address;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != -1) {
cout << "WINSOCK2 Initialized" << endl;
if((serversock = socket(PF_INET, SOCK_DGRAM, PF_UNSPEC)) != SOCKET_ERROR) {
cout << "Socket Created" << endl;
unsigned long NB = 1;
ioctlsocket(serversock, FIONBIO, &NB);
server_address.sin_family = AF_INET;
server_address.sin_addr = *((struct in_addr *)server);
server_address.sin_port = htons(21578);
if(bind(serversock, (struct sockaddr*)&server_address, sizeof(struct sockaddr) == 0)) {
cout << "Network bound" << endl;
cout << "Listening..." << endl;
listen(serversock, 5);
while(1) {
int size = sizeof((struct sockaddr *)server);
SOCKET clientsock = accept(serversock, (struct sockaddr *)server, &size);
char INCOMMAND[20];
if(clientsock >= 0) {
if(recv(clientsock, INCOMMAND, sizeof(INCOMMAND), 0)) {
int i = 0;
if(INCOMMAND == "SVR --WINSOCK-VERIFY\0") {
cout << "SVR receieved" << endl;
}
while(INCOMMAND[i] != '\0') {
cout << INCOMMAND[i];
i++;
}
cout << endl;
}
else {
cout << "ERROR - Could not receive command" << endl;
break;
}
}
}
}
else {
cout << "ERROR - Could not bind network. " << "Error: " << WSAGetLastError() << endl;
closesocket(serversock);
WSACleanup();
}
}
else {
cout << "ERROR - Could not create the socket. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
}
else {
cout << "ERROR - Could not initialize WINSOCK2. " << "Error: " << WSAGetLastError() << endl;
WSACleanup();
}
Calls to send/recv may not send/receive the amount of bytes you indicate in their third argument, in fact, most of the time they will send/receive less bytes than you expect. You usually have to loop until the entire data has been sent/received. Also note that doing this:
char buffer[100];
recv(clientsock, buffer, sizeof(buffer), 0);
cout << buffer;
Will most surelly print garbage, since you don't have a null terminator in your char array(whatch out for buffer overflows when appending it), and you're not checking the return value of recv. It might be reading 1 byte only(or none if an error ocurred). You're printing your buffer the same way in your server app.
In this case, you are actually sending the null-terminator, but since you might read less bytes than you expect, this character might not be received by the other application, thus printing it will print garbage chars.
Edit: You should have a look at the structure of a sockaddr struct. You can have a look at it here. In your code you are using this convertion:
int size = sizeof((struct sockaddr *)"127.0.0.1");
const char *, which is the type of "127.0.0.1", cannot be casted to a sockaddr pointer, they're incompatible. Here you should use getaddrinfo in order to resolve the IP address(note that you could use a domain name, and this function would resolve it). There are lots of tutorials online on how to use this function, just search for "getaddrinfo".