So I have a winsock application in which the computer tries to accept a client, and then starts a new thread with the a pointer to the class object with client info which it copies and then deletes with the delete keyword.
The backbone is copied but the beginning of the OOP-structure is my work and the current implementation seems to be giving me some issues.
I noticed the socket might not copy in the correct format, but have no idea on how to fix this. As the client tries to connect it throws me the error message of that the server refused the connection. Anyway, here is the code of the server.
UPDATE:
It's working.
// main.h
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <process.h>
#include <cstring>
#include <iostream>
#include <stdio.h>
#include <memory>
#pragma comment(lib,"ws2_32.lib" )
class clientData{
private:
SOCKET clientSocket;
std::string name;
public:
clientData(SOCKET &clientSock, const char *tName);
clientData(clientData *cliDat);
~clientData();
inline SOCKET *getClientSocket(){
return &clientSocket;
}
inline std::string *getName(){
return &name;
}
};
And here is the main cpp file
// main.cpp
#include "main.h"
unsigned int __stdcall ServClient(void *data);
int main(int argc, char *argv[])
{
WSADATA wsaData;
int iResult;
sockaddr_in addr;
SOCKET sock, client[10];
addr.sin_family = AF_INET;
addr.sin_port = htons(13337);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);//2.2
if (iResult)
{
printf("WSA startup failed");
return 0;
}
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
printf("Invalid socket");
return 0;
}
int addrlen = sizeof(sockaddr_in);
iResult = bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in));
if (iResult)
{
printf("bind failed %u", GetLastError());
return 0;
}
iResult = listen(sock, SOMAXCONN);
if (iResult)
{
printf("iResult failed %u", GetLastError());
return 0;
}
int iterationCount = 0;
while ((iterationCount < 10 &&
(client[iterationCount] = accept(sock, (SOCKADDR*)&addr, &addrlen)) != SOCKET_ERROR))
{
if (client[iterationCount] == INVALID_SOCKET){
printf("invalid client socket",GetLastError());
continue;
}
++iterationCount;
char tempName[100] = { '\0' };
sprintf_s(tempName, sizeof(tempName), "Client %u", iterationCount);
clientData *tempCLdata = new clientData(client[iterationCount - 1], tempName);
_beginthreadex(0, 0, ServClient, (void*)tempCLdata, 0, 0);
tempCLdata = nullptr;
}
return 0;
}
unsigned int __stdcall ServClient(void *data)
{
clientData cliDat((clientData*)data);
delete (clientData*)data;
printf("Client connected\n");
int recvLen = 1;
char chunk[1024] = { '\0' };
while ((recvLen = recv(*cliDat.getClientSocket(), chunk, 1024, 0)) > 0){
printf("%.*s", recvLen, chunk);
}
if (recvLen == -1)
perror("Socket recv() problem..\n");
else
printf("End of data on socket, closing..\n");
closesocket(*cliDat.getClientSocket());
return 0;
}
clientData::clientData(SOCKET &clientSock, const char *tName){
clientSocket = clientSock;
name.assign(tName);
}
clientData::clientData(clientData *cliDat){
SOCKET *clientSocketPtr = cliDat->getClientSocket();
clientSocket = *clientSocketPtr;
name.assign(cliDat->getName()->c_str());
}
clientData::~clientData(){
}
Also here is the relevant bit of client code, as requested.
char buffer[1023] = { '\0' };
int heartbeatCount = 0;
while (true)
{
sprintf_s(buffer, sizeof(buffer), "Heartbeat %d", heartbeatCount + 1);
send(sock, buffer, strlen(buffer) + 1, 0);
++heartbeatCount;
Sleep(1000);
}
Related
#include <stdio.h>
#include <time.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "WS2_32.lib")
#define IP_ADDRESS "127.0.0.1"
#define PORT 20000
#define BUF_SIZE 64
#undef FD_SETSIZE
#define FD_SETSIZE 10000
void shuffle_buffer(char* buf, size_t size);
SOCKET create_socket();
void send_data(SOCKET sock);
int main()
{
WSADATA ws;
if (WSAStartup(MAKEWORD(2, 2), &ws) != 0)
{
printf("Init Windows Socket Failed::%d\n", GetLastError());
return -1;
}
const int CLIENT_SIZE = 1;
SOCKET socks[CLIENT_SIZE];
struct timeval tv = { 0, 10 };
fd_set fd_read, fd_write;
FD_ZERO(&fd_read);
FD_ZERO(&fd_write);
for (int i = 0; i < CLIENT_SIZE; i++) {
SOCKET sock = create_socket();
socks[i] = sock;
FD_SET(sock, &fd_write);
FD_SET(sock, &fd_read);
}
Sleep(1000);
int number_to_recv = CLIENT_SIZE;
while (number_to_recv > 0) {
int ret = select(CLIENT_SIZE, &fd_read, &fd_write, NULL, &tv);
for (int i = 0; i < CLIENT_SIZE; i++) {
if (FD_ISSET(socks[i], &fd_read)) {
char buf[BUF_SIZE];
int n = recv(socks[i], buf, BUF_SIZE, 0);
buf[n] = 0;
printf("%s\n", buf);
number_to_recv--;
}
if (FD_ISSET(socks[i], &fd_write)) {
send_data(socks[i]);
FD_CLR(socks[i], &fd_write);
//Sleep(1);
}
}
//printf("ret and number : %d, %d\n", ret, number_to_recv);
}
for (int i = 0; i < CLIENT_SIZE; i++) {
closesocket(socks[i]);
}
WSACleanup();
}
SOCKET create_socket()
{
SOCKET cli_sock;
struct sockaddr_in addr;
if ((cli_sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Create Socket Failed::%d\n", GetLastError());
return -1;
}
//inet_pton
memset(addr.sin_zero, 0x00, 8);
addr.sin_family = AF_INET;
inet_pton(AF_INET, IP_ADDRESS, (void*)(&addr.sin_addr.s_addr));
addr.sin_port = htons(PORT);
if (connect(cli_sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
printf("Connect Error::%d\n", GetLastError());
return -1;
}
return cli_sock;
}
void send_data(SOCKET sock)
{
const int SEND_SIZE = BUF_SIZE / 2;
char buf[SEND_SIZE] = { 0 };
memset(buf, 'a', SEND_SIZE);
shuffle_buffer(buf, SEND_SIZE);
if (send(sock, buf, SEND_SIZE, 0) == SOCKET_ERROR)
{
printf("Send Info Error::%d\n", GetLastError());
}
}
void shuffle_buffer(char* buf, size_t size)
{
for (int i = 0; i < size; i++) {
buf[i] += int(rand() % 26);
}
}
Code above is a socket client using select model run on Win10, the problem is after I send data, but I can not receive data(I am sure that server has sent back data), this code below doesn`t run, so what is the problem? Thanks
The first parameter in select is maxfdp, and I know the difference between Win and Unix, so on Windows, this parameter seems not necessary, and I can write data,
but can not receive it.
if (FD_ISSET(socks[i], &fd_read)) {
char buf[BUF_SIZE];
int n = recv(socks[i], buf, BUF_SIZE, 0);
buf[n] = 0;
printf("%s\n", buf);
number_to_recv--;
}
select removes the sockets from the fd_set if they are not readable/writable. You need to add them back in before the next time you call select.
The reason your code can write data is because sockets start out being writable, so they will still be set in fd_write and your code will write data. They don't start out being readable, if no data has been received yet, so they'll be removed from the fd_read set and then your code stops checking whether they are readable.
If I launch 2 instances of the code below in the same computer the multicast works fine.
If I launch it on a different computer in the same network I won't receive anything.
Any idea what could be wrong? This code should compile as is.
I am testing on win10 but I get similar results when I run this on linux.
#include "pch.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "winsock2.h"
#include <iostream>
#include <conio.h>
#include <thread>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
char mcastGroup[] = "224.1.2.3";
int mcastPort = 5435;
int CreateSocket()
{
return socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}
void JoinGroup(int sck)
{
struct ip_mreq grp;
grp.imr_multiaddr.s_addr = inet_addr(mcastGroup);
grp.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sck, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&grp, sizeof(grp)) < 0)
{
printf("Error in joining group\n");
closesocket(sck);
exit(1);
}
}
int receiver()
{
int sck = CreateSocket();
int reuse = 1;
if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Socket reuse address error\n");
closesocket(sck);
exit(1);
}
JoinGroup(sck);
struct sockaddr_in lclSck;
memset((char *)&lclSck, 0, sizeof(lclSck));
lclSck.sin_family = AF_INET;
lclSck.sin_port = htons(mcastPort);
lclSck.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sck, (struct sockaddr*)&lclSck, sizeof(lclSck)))
{
perror("Error in binding socket\n");
closesocket(sck);
exit(1);
}
while (1)
{
int blen;
char buf[1024];
blen = sizeof(buf);
memset(buf, 0, blen);
struct sockaddr_in addrin;
int addrinlen = sizeof(addrin);
memset(&addrin, 0, sizeof(addrin));
int res = recvfrom(sck, buf, blen, 0, (sockaddr *)&addrin, &addrinlen);
if (res<0)
{
printf("Message read error\n");
closesocket(sck);
exit(1);
}
else
{
printf(": %s\n", buf);
}
}
return 0;
}
int sender()
{
int sck = CreateSocket();
struct in_addr lclInterface;
lclInterface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sck, IPPROTO_IP, IP_MULTICAST_IF, (char *)&lclInterface, sizeof(lclInterface)) < 0)
{
printf("Local interface error\n");
exit(1);
}
else
{
printf("Local interface set\n");
}
u_char ttl = 5;
setsockopt(sck, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
while (1)
{
int blen;
char buf[1024];
blen = sizeof(buf);
memset(buf, 0, blen);
for (int i = 0; i < 100; i++)
{
fgets(buf, blen, stdin);
sockaddr_in grpSck;
memset((char *)&grpSck, 0, sizeof(grpSck));
grpSck.sin_family = AF_INET;
grpSck.sin_port = htons(mcastPort);
grpSck.sin_addr.s_addr = inet_addr(mcastGroup);
if (sendto(sck, buf, blen, 0, (struct sockaddr*)&grpSck, sizeof(grpSck)) < 0)
{
printf("Error in sending message");
}
}
}
return 0;
}
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
std::thread t1([&] { receiver(); return 0; });
sender();
WSACleanup();
}
This code should work, the problem was that I was using IP_MULTICAST_IF, that forces to use a network interface different from the default one. In case one needs to use such a thing I was able to get the multicast working by following
Thanks to Remy Lebeau advice, that is to make sure you are binding the sockets to IPs that are in the same network.
Here is working code the code:
#ifdef WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
#include <thread>
char mcastGroup[] = "224.1.2.3";
int mcastPort = 5435;
void PrintAddrIn(sockaddr_in addr_in)
{
char str[255];
inet_ntop(AF_INET, &addr_in.sin_addr, (char *)str, sizeof(str));
printf("%s", str);
}
int receiver(int sck)
{
while (1)
{
char buf[1024];
memset(buf, 0, sizeof(buf));
struct sockaddr_in addrin;
socklen_t addrinlen = sizeof(addrin);
memset(&addrin, 0, sizeof(addrin));
int res = recvfrom(sck, buf, sizeof(buf), 0, (sockaddr *)&addrin, &addrinlen);
if (res<0)
{
printf("Message read error\n");
exit(1);
}
else
{
PrintAddrIn(addrin); printf(": %s\n", buf);
}
}
return 0;
}
int sender(int sck)
{
while (1)
{
sockaddr_in grpSck;
memset((char *)&grpSck, 0, sizeof(grpSck));
grpSck.sin_family = AF_INET;
grpSck.sin_port = htons(mcastPort);
grpSck.sin_addr.s_addr = inet_addr(mcastGroup);
for (int i = 0; i < 100; i++)
{
char buf[1024];
fgets(buf, sizeof(buf), stdin);
if (sendto(sck, buf, strlen(buf), 0, (struct sockaddr*)&grpSck, sizeof(grpSck)) < 0)
{
printf("Error in sending message");
exit(1);
}
}
}
return 0;
}
int main()
{
#ifdef WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
int sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Set reuse
//
int reuse = 1;
if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Socket reuse address error\n");
exit(1);
}
else
{
printf("Socket reuse address successfull\n");
}
// Join mcast group
//
struct ip_mreq grp;
grp.imr_multiaddr.s_addr = inet_addr(mcastGroup);
grp.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sck, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&grp, sizeof(grp)) < 0)
{
printf("Error in joining group\n");
exit(1);
}
else
{
printf("Group joined successfully\n");
}
// Bind socket
//
struct sockaddr_in lclSck;
memset((char *)&lclSck, 0, sizeof(lclSck));
lclSck.sin_family = AF_INET;
lclSck.sin_port = htons(mcastPort);
lclSck.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sck, (struct sockaddr*)&lclSck, sizeof(lclSck)))
{
perror("Error in binding socket\n");
exit(1);
}
else
{
printf("Socket binding successfull\n");
}
u_char ttl = 5;
setsockopt(sck, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
std::thread t1([&] { receiver(sck); return 0; });
sender(sck);
#ifdef WIN32
WSACleanup();
#endif
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am writing a network client-server program:
Server side:
#include "stdafx.h"
#include <winsock.h>
#include <stdio.h>
#include<stdlib.h>
#define PROTOPORT 5193
#define QLEN 6
#define BUFFERSIZE 512
void ErrorHandler(char *errorMessage)
{
printf(errorMessage);
}
void ClearWinSock()
{
#if defined WIN32
WSACleanup();
#endif
}
int main(int argc, char *argv[])
{
int port;
if (argc > 1)
port = atoi(argv[1]);
else
port = PROTOPORT;
if (port < 0) {
printf("Bad port number %s \n", argv[1]);
return 0;
}
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
ErrorHandler("Error at WSAStartup()\n");
return 0;
}
#endif
//creazione della socket
int MySocket;
MySocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (MySocket < 0) {
ErrorHandler("socket creation failed.\n");
ClearWinSock();
return 0;
}
//ASSEGNAZIONE DI UN INDIRIZZO ALLA SOCKET
struct sockaddr_in sad;
memset(&sad, 0, sizeof(sad)); // ensures that extra bytes contain 0
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr("127.0.0.1");
sad.sin_port = htons(port); /* converts values between the host and
network byte order. Specifically, htons() converts 16-bit quantities
from host byte order to network byte order. */
if (bind(MySocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
ErrorHandler("bind() failed.\n");
closesocket(MySocket);
ClearWinSock();
return 0;
}
// SETTAGGIO DELLA SOCKET ALL'ASCOLTO
if (listen(MySocket, QLEN) < 0) {
ErrorHandler("listen() failed.\n");
closesocket(MySocket);
ClearWinSock();
return 0;
}
// ACCETTARE UNA NUOVA CONNESSIONE
struct sockaddr_in cad; // structure for the client address
int clientSocket; // socket descriptor for the client
int clientLen; // the size of the client address
printf("Waiting for a client to connect...");
while (1) {
clientLen = sizeof(cad); // set the size of the client address
if ((clientSocket = accept(MySocket, (struct sockaddr *)&cad,
&clientLen)) < 0) {
ErrorHandler("accept() failed.\n");
//RICEZIONE DATI TEST
int bytesRcvd;
int totalBytesRcvd = 0;
int Csocket;
Csocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
char buf[BUFFERSIZE]; // buffer for data from the server
printf("Received: "); // Setup to print the echoed string
if ((bytesRcvd = recv(Csocket, buf, BUFFERSIZE - 1, 0)) <= 0) {
ErrorHandler("recv() failed or connection closed prematurely");
closesocket(Csocket);
ClearWinSock();
return 0;
}
totalBytesRcvd += bytesRcvd; // Keep tally of total bytes
buf[bytesRcvd] = '\0'; // Add \0 so printf knows where to stop
printf("%s", buf); // Print the echo buffer
// CHIUSURA DELLA CONNESSIONE
closesocket(MySocket);
ClearWinSock();
return 0;
}
printf("Handling client %s\n", inet_ntoa(cad.sin_addr));
}
}
and client side:
#include "stdafx.h"
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFERSIZE 512
#define PROTOPORT 5193
void ErrorHandler(char *errorMessage) {
printf(errorMessage);
}
void ClearWinSock() {
WSACleanup();
}
int main(void) {
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("error at WSASturtup\n");
return 0;
}
// CREAZIONE DELLA SOCKET
int Csocket;
Csocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Csocket < 0) {
ErrorHandler("socket creation failed.\n");
closesocket(Csocket);
ClearWinSock();
return 0;
}
// COSTRUZIONE DELL’INDIRIZZO DEL SERVER
struct sockaddr_in sad;
memset(&sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr("127.0.0.1"); // IP del server
sad.sin_port = htons(5193); // Server port
// CONNESSIONE AL SERVER
if (connect(Csocket, (struct sockaddr *)&sad, sizeof(sad)) < 0)
{
ErrorHandler("Failed to connect.\n");
closesocket(Csocket);
ClearWinSock();
return 0;
}
char* inputString = "prova"; // Stringa da inviare
int stringLen = strlen(inputString); // Determina la lunghezza
// INVIARE DATI AL SERVER
if (send(Csocket, inputString, stringLen, 0) != stringLen) {
ErrorHandler("send() sent a different number of bytes than expected");
closesocket(Csocket);
ClearWinSock();
return 0;
}
// RICEVERE DATI DAL SERVER
int bytesRcvd;
int totalBytesRcvd = 0;
char buf[BUFFERSIZE]; // buffer for data from the server
printf("Received: "); // Setup to print the echoed string
while (totalBytesRcvd < stringLen) {
if ((bytesRcvd = recv(Csocket, buf, BUFFERSIZE - 1, 0)) <= 0) {
ErrorHandler("recv() failed or connection closed prematurely");
closesocket(Csocket);
ClearWinSock();
return 0;
}
totalBytesRcvd += bytesRcvd; // Keep tally of total bytes
buf[bytesRcvd] = '\0'; // Add \0 so printf knows where to stop
printf("%s", buf); // Print the echo buffer
}
// CHIUSURA DELLA CONNESSIONE
closesocket(Csocket);
ClearWinSock();
printf("\n"); // Print a final linefeed
system("pause");
return(0);
}
I have problems in output the string i've passed from client to server: "prova".
Can someone tell me where is error? The code doesn't give me any error.
You are receiving data only when accept failed:
if ((clientSocket = accept(MySocket, (struct sockaddr *)&cad,
&clientLen)) < 0) {
ErrorHandler("accept() failed.\n");
int bytesRcvd;
int totalBytesRcvd = 0;
...
What you need to do is just add a else case:
if ((clientSocket = accept(MySocket, (struct sockaddr *)&cad,
&clientLen)) < 0) {
ErrorHandler("accept() failed.\n");
} else {
int bytesRcvd;
int totalBytesRcvd = 0;
... // receive code here
// clientSocket is the socket to communicate with client
// call recv on it, not the other socket you created in the loop
}
The accept() call returns 'clientSocket', which you promptly ignore and dream up some new 'Csocket' to receive on.
Don't do that.
if ((bytesRcvd = recv(clientSocket, buf, BUFFERSIZE - 1, 0)) <= 0) {
This is the new Server side:
#include "stdafx.h"
#include <winsock.h>
#include <stdio.h>
#include<stdlib.h>
#define PROTOPORT 5193
#define QLEN 6
#define BUFFERSIZE 512
void ErrorHandler(char *errorMessage)
{
printf(errorMessage);
}
void ClearWinSock()
{
#if defined WIN32
WSACleanup();
#endif
}
int main(int argc, char *argv[])
{
int port;
if (argc > 1)
port = atoi(argv[1]);
else
port = PROTOPORT;
if (port < 0) {
printf("Bad port number %s \n", argv[1]);
return 0;
}
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
ErrorHandler("Error at WSAStartup()\n");
return 0;
}
#endif
//creazione della socket
int MySocket;
MySocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (MySocket < 0) {
ErrorHandler("socket creation failed.\n");
ClearWinSock();
return 0;
}
//ASSEGNAZIONE DI UN INDIRIZZO ALLA SOCKET
struct sockaddr_in sad;
memset(&sad, 0, sizeof(sad)); // ensures that extra bytes contain 0
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr("127.0.0.1");
sad.sin_port = htons(port); /* converts values between the host and
network byte order. Specifically, htons() converts 16-bit quantities
from host byte order to network byte order. */
if (bind(MySocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
ErrorHandler("bind() failed.\n");
closesocket(MySocket);
ClearWinSock();
return 0;
}
// SETTAGGIO DELLA SOCKET ALL'ASCOLTO
if (listen(MySocket, QLEN) < 0) {
ErrorHandler("listen() failed.\n");
closesocket(MySocket);
ClearWinSock();
return 0;
}
// ACCETTARE UNA NUOVA CONNESSIONE
struct sockaddr_in cad; // structure for the client address
int clientSocket; // socket descriptor for the client
int clientLen; // the size of the client address
printf("Waiting for a client to connect...");
while (1) {
clientLen = sizeof(cad); // set the size of the client address
if ((clientSocket = accept(MySocket, (struct sockaddr *)&cad,
&clientLen)) < 0) {
ErrorHandler("accept() failed.\n");
}else{
//RICEZIONE DATI TEST
int bytesRcvd;
int totalBytesRcvd = 0;
char buf[BUFFERSIZE]; // buffer for data from the server
printf("Received: "); // Setup to print the echoed string
if ((bytesRcvd = recv(clientSocket, buf, BUFFERSIZE - 1, 0)) <= 0) {
ErrorHandler("recv() failed or connection closed prematurely");
closesocket(clientSocket);
ClearWinSock();
return 0;
totalBytesRcvd += bytesRcvd; // Keep tally of total bytes
buf[bytesRcvd] = '\0'; // Add \0 so printf knows where to stop
printf("%s", buf); // Print the echo buffer
} Sleep(10);
// CHIUSURA DELLA CONNESSIONE
closesocket(MySocket);
ClearWinSock();
return 0;
}
printf("Handling client %s\n", inet_ntoa(cad.sin_addr));
system("pause");
}
}
Yesterday I started writing a code for server-client TCP/IP for chating.
It's code for server:
#include <iostream>
#include <winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
int main() {
WSAData wsa;
WORD Version = MAKEWORD(2, 1);
WSAStartup(Version, &wsa);
SOCKET Listen = socket(AF_INET, SOCK_STREAM, 0);
SOCKET Connect = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN Server;
Server.sin_addr.s_addr = inet_addr("127.0.0.1");
Server.sin_family = AF_INET;
Server.sin_port = htons(100);
bind(Listen, (SOCKADDR*)&Server, sizeof(Server));
listen(Listen, 1);
int size = sizeof(Server);
char buffer[512];
char *fn = "";
int iResult;
std::cout <<"Listening...";
if(Connect = accept(Listen, (SOCKADDR*)&Server, &size)) {
std::cout << "\nConnecting was reached :)";
}
do {
char *fn;
iResult = recv(Connect, buffer, sizeof(buffer), 0);
if (iResult > 0) {
buffer[iResult] = '\0';
fn = buffer;
std::cout << fn;
} else if (iResult == 0){
printf("Connection closing...\n");
iResult = 0;
}
} while (iResult > 0);
WSACleanup();
std::cin.get();
return 0;
}
And it's for client:
#include <iostream>
#include <winsock2.h>
#include <string>
#pragma comment(lib, "Ws2_32.lib")
int main() {
WSAData wsa;
WORD Version = MAKEWORD(2, 1);
WSAStartup(Version, &wsa);
int iResult;
std::string text;
char buffer[512];
SOCKADDR_IN Client;
Client.sin_addr.s_addr = inet_addr("127.0.0.1");
Client.sin_family = AF_INET;
Client.sin_port = htons(100);
SOCKET Connect = socket(AF_INET, SOCK_STREAM, 0);
std::cout << "Wcisnij enter aby polaczyc";
std::cin.get();
if(connect(Connect, (SOCKADDR*)&Client, sizeof(Client))) {
std::cout << "Nawiazano polaczeniee";
}
do {
std::cout << "Waxer: ";
std::cin >> text;
text.insert( 0, "Waxer: " );
strcpy_s(buffer, text.c_str());
// Send an initial buffer
iResult = send(Connect, buffer, strlen(buffer), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(Connect);
WSACleanup();
return 1;
}
} while(text != "ban");
std::cout<< "Polaczenie wyslane!";
std::cin.get();
return 0;
}
My question is? What should I change in this code for multiple clients. I mean how to connect new clients?
Your question is quite open, but in general you need threads.
Pseudocode:
int main()
{
std::vector<std::thread> clients;
Socket listener("localhost", "1337");
for (;;)
{
Socket tmp = listener.accept();
clients.push_back(std::thread(&myHandlerFunction, tmp));
clients.back().detach();
}
}
In the end you have a thread for every connected client and can codify your chat logic so that they can communicate with each other.
I'm new to socket programming and I have this client that tries to connect to a server on the same computer. But the server hangs there after bind or accept—cause bind seems to be right but no output. I know that the server works because another client can connect just fine and the client seems to have done that. What causes the server to not see this incoming connection? I'm at the end of my wits here.
And I haven't been used to programming on Mac, so thank you so much for your patience if I have made some foolish mistakes.
My code is as follows:
server.cpp
using namespace std;
#include<iostream>
#include <netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define PORT 8888
#define BACKLOG 20
//#define DEST_IP "127.0.0.1"
int process_conn_server(int s)
{
ssize_t size =0;
char buffer[1024];
for( ; ; )
{
size = read(s,buffer,1024);
if(size == 0)
{
return 0;
}
}
sprintf(buffer, "%d bytes altogether\n", (int)size);
write(s, buffer,strlen(buffer)+1);
return 0;
}
int main(int argc,char *argv[])
{
//cout<<"?";
int ss, sc, r, err;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int opt=1;
pid_t pid;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
ss = socket(AF_INET, SOCK_STREAM, 0);
if(ss<0)
{
cout<<"[process infro]socket error"<<endl;
return -1;
}
cout<<"[process infro]socket successful"<<endl;
r = setsockopt(ss, SOL_SOCKET,SO_REUSEADDR, (void*)&opt,sizeof(opt));
if (r == -1)
{
perror("setsockopt(listen)");
return 0;
}
cout<<"[process infro]sockopt successful"<<endl;
cout<<"?";
err = bind(ss, (struct sockaddr*) &server_addr, sizeof( server_addr));
cout<<"err";
if(err < 0)
{
cout<<"[process infro]bind error"<<endl;
return -1;
}
cout<<"[process infro]bind successful";
err=listen(ss, BACKLOG);
if(err <0)
{
cout<<"[process infro]listen error"<<endl;
return -1;
}
cout<<"[process infro]lisen successful";
for( ; ; )
{
int addrlen = sizeof(struct sockaddr);
sc = accept(ss, (struct sockaddr*)&client_addr, (socklen_t *)&addrlen);
if(sc < 0)
{
continue;
}
pid = fork();
if (pid == 0)
{
close(ss);
process_conn_server(sc);
}
else
{
close(sc);
}
}
//opt=0;
//setsockopt(ss,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(len));
}
client.cpp
using namespace std;
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <time.h>
#include <arpa/inet.h>
#include <fstream.h>
#define PORT 8888
#define DEST_IP "127.0.0.1"
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[1024];
//read from the file to be sent
fstream outfile("programm.txt",ios::in|ios::out);
if (outfile.fail())
{
printf("[process infro]cannot open the file to be sent\n");
return ;
}
printf("[process infro]successfully open the file to be sent\n");
while(!outfile.eof())
{
outfile.getline(buffer,1025,'\n');
write(s,buffer,1024);
size = read(s, buffer, 1024);
if(size = 0)
{
return ;
}
//write to the server
write(s,buffer,size);
//get response from the server
size=read(s,buffer,1024);
write(1,buffer,size);
}
outfile.close(); //关闭文件
}
int main(int argc,char *argv[])
{
int s;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(DEST_IP);
server_addr.sin_port = htons(PORT);
s = socket(AF_INET, SOCK_STREAM, 0);
if(s < 0)
{
cout<<"[process infro]socke error"<<endl;
return -1;
}
cout<<"[process infro] socket built successfully\n";
//inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
cout<<"[process infor] connected\n";
process_conn_client(s);
close(s);
return 0;
}
This may be unrelated.... but it won't fit in a comment...
In your server you do this:
int process_conn_server(int s)
{
ssize_t size =0;
char buffer[1024];
for( ; ; )
{
// keep reading until read returns 0
size = read(s,buffer,1024);
if(size == 0)
{
return 0;
}
}
sprintf(buffer, "%d bytes altogether\n", (int)size);
write(s, buffer,strlen(buffer)+1);
return 0;
}
In your client you do this:
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[1024];
//read from the file to be sent
fstream outfile("programm.txt",ios::in|ios::out);
if (outfile.fail())
{
printf("[process infro]cannot open the file to be sent\n");
return ;
}
printf("[process infro]successfully open the file to be sent\n");
while(!outfile.eof())
{
outfile.getline(buffer,1025,'\n');
// write to server?
write(s,buffer,1024);
// read from server?
size = read(s, buffer, 1024);
if(size = 0)
{
return ;
}
//write to the server
write(s,buffer,size);
//get response from the server
size=read(s,buffer,1024);
write(1,buffer,size);
}
outfile.close();
}
It's a bit hard to follow because of your variable names, but it looks like your client is working under the assumption that your server will send back a response for every chunk of data received, which isn't the case. You server doesn't appear to have changed the accepted socket to non-blocking, so it's going to block on the read call until there is some data to read (it's never going to get 0)...
Are you sure it's failing before this point? Do you have some sample output?
Aso, in your call to accept, you pass addrlen...
int addrlen = sizeof(struct sockaddr);
I think this should be:
int addrlen = sizeof(struct sockaddr_in); /* sizeof(client_addr) */