I'm working on a networking project. I can successfully send a single message from my client program over to my server program. However, when I send a second message, the server apparently isn't receiving it. I say this because the client program generates output to suggest that the message was sent, but the server shows no reaction at all.
I'm thinking that I am doing something wrong with either select() or FD_ISSET(). Can anyone see what I am doing wrong? Thanks.
int main(int argc, char *argv[]) {
int sockfd, newfd;
struct sockaddr_in clientAddr;
unsigned int recvLen;
socklen_t addr_size = sizeof clientAddr;
fd_set read_set;
struct timeval tv;
char buffer[BUFFSIZE];
// prepare the address struct for the first client
bzero(&clientAddr,sizeof(clientAddr)); //zero the struct
clientAddr.sin_family = AF_INET; //address family (ipv4)
clientAddr.sin_port = htons(SERVER_PORT); //sets port to network byte order
clientAddr.sin_addr.s_addr = INADDR_ANY;
// create a listening connection to listen for requests from clients
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stdout, "Cannot create socket for client 0.\n");
fprintf(stdout, "Terminating program\n\n");
exit(1);
}
if (bind(sockfd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
fprintf (stdout, "Binding failed for client 0\n\n");
perror("bind failed");
exit (1);
}
if (listen(sockfd, 10) < 0) {
fprintf (stdout, "Listen() failed\n");
perror("listen() failed");
exit (1);
}
// accept the connection
if ((newfd = accept(sockfd, (struct sockaddr *)&clientAddr, &addr_size)) < 0) {
fprintf(stdout, "Error accepting inbound data from client 0\n");
perror(" accept() failed");
exit(EXIT_FAILURE);
}
// initialize the fd set
FD_ZERO(&read_set);
FD_SET(newfd, &read_set); // adding our socket to the set
tv.tv_sec = 0;
tv.tv_usec = TIMEOUT * 1000;
while (1) {
if ( select(newfd+1, &read_set, NULL, NULL, &tv) == -1) {
perror("select failure");
fprintf(stdout, "errno: %d\n", errno);
exit(EXIT_FAILURE);
}
if (FD_ISSET(newfd, &read_set)) {
bzero(buffer, BUFFSIZE);
recv(newfd, &buffer, BUFFSIZE, 0);
fprintf(stdout, "Received message: %s\n", buffer);
}
}
return 0;
}
After each select you need call FD_ZERO(&read_set); FD_SET(newfd, &read_set); again.
So just move those functions into the loop, before select.
Related
I'm not able to connect to a TCP server on a computer from a client in another computer on the same local network. I'm Getting an error 10060.
I'm able to connect to the server if the client is launched on the same computer as the server.
Here's some info about the server, then the client
(client running on .30 , server = .50)
TCP info of client
Here we can see that my client is sending a SYN signal to the correct IP/PORT
TCP info of Server
The server seems to be listening to any IP and port. So it sounds like I'm not understanding how to set up setsockopt.
Here's the main() of the server that doesnt work if the client isn't on the same computer:
int main(int argc, char **argv){
if(argc != 2){
printf("Usage: %s <port>\n", argv[0]);
return EXIT_FAILURE;
}
// Start of experiment
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
{
printf("The Winsock 2.2 dll was found okay\n");
}
char *ip = "127.0.0.1";
int port = atoi(argv[1]);
//int option = 1;
bool option = TRUE;
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
pthread_t tid;
/* Socket settings */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(port);
/* Ignore pipe signals */
//signal(SIGPIPE, SIG_IGN); Sigpipe doesnt exist in NT. I need to implement something ...
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *) &option, sizeof(option)) < 0){
perror("ERROR: setsockopt failed\n");
printf("Error : %i\n",WSAGetLastError());
printf("port was: %i\n",port);
printf("Ip Was : %lu\n",serv_addr.sin_addr.s_addr);
WSACleanup();
return EXIT_FAILURE;
}
/* Bind */
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR: Socket binding failed");
WSACleanup();
return EXIT_FAILURE;
}
/* Listen */
if (listen(listenfd, 10) < 0) {
perror("ERROR: Socket listening failed");
WSACleanup();
return EXIT_FAILURE;
}
printf("=== WELCOME TO THE CHATROOM ===\n");
while(1){
socklen_t clilen = sizeof(cli_addr);
connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
/* Check if max clients is reached */
if((cli_count + 1) == MAX_CLIENTS){
printf("Max clients reached. Rejected: ");
print_client_addr(cli_addr);
printf(":%d\n", cli_addr.sin_port);
close(connfd);
continue;
}
/* Client settings */
client_t *cli = (client_t *)malloc(sizeof(client_t));
cli->address = cli_addr;
cli->sockfd = connfd;
cli->uid = uid++;
/* Add client to the queue and fork thread */
queue_add(cli);
pthread_create(&tid, NULL, &handle_client, (void*)cli);
/* Reduce CPU usage */
sleep(1);
}
WSACleanup();
return EXIT_SUCCESS;
}
I somehow managed to make it work when messing around parameters, but I'm not able to reproduce it since I don't understand how winsock works yet.
I tried to disable Firewall on both computers, but it didn't help.
Thanks a lot for your help !
I'm trying to implement an application using select(), but without closing the socket already served and without removing the corrispondent file descriptor from the main set of monitored socket (at least not immediatly). The goal is to create something similar to a set of "persistent connections".
The problem is that after I checked the ready socket, recv() continue to receive the last message a peer sent (running the code below, "Received" is printed infinited times). My thought is that the socket is still "ready", but I can't "mark" it as "unready" or "unchecked" to check it again only if there's a new message from that peer, and close it only in determinate conditions. How can I mark that socket as unready without close it? Is there another solution to implement persistent connections with select()?
Here it is a code of a simple application that I'm trying to program to understand how to realize persistent connections.
Server:
int main () {
int ret, sd, new_sd, len, i;
char buffer[1024];
fd_set master;
fd_set read_fds;
int fdmax;
struct sockaddr_in my_addr;
FD_ZERO(&master);
FD_ZERO(&read_fds);
sd = socket(AF_INET, SOCK_STREAM, 0);
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(4257);
my_addr.sin_addr.s_addr = INADDR_ANY;
ret = bind(sd, (struct sockaddr*)&my_addr, sizeof(my_addr));
if(ret<0) {
perror("Error: ");
exit(1);
}
ret = listen(sd,10);
if(ret<0) {
perror("Error: ");
exit(-1);
}
FD_SET(sd, &master);
fdmax = sd;
for(;;) {
read_fds = master;
select(fdmax+1, &read_fds, NULL, NULL, NULL);
for(i=0; i<=fdmax; i++) {
if(FD_ISSET(i, &read_fds)) {
if(i == sd) {
len = sizeof(cl_addr);
new_sd = accept(sd, (struct sockaddr*)&cl_addr, &len);
FD_SET(new_sd, &master);
if(new_sd > fdmax)
fdmax = new_sd;
}
else {
ret = recv(i, buffer, 4, 0);
printf("Error: %s\n", strerror(errno));
printf("Received.\n");
if(strcmp(buffer, "DEL")==0) { /*Connection is closed only if client request it*/
close(i);
FD_CLR(i, &master);
printf("%d closed.\n",i);
continue;
}
len=strlen(buffer);
ret = send(i, (void*)buffer, len, 0);
if(ret<0) {
printf("socket n%d :\n",i);
perror("Error \n");
}
}
}
}
}
close(sd);
return 0;
}
I would be really grateful if you would help me, it is very important to me.
Edit: Client side is correct and send only once. "printf("Error: %s\n", strerror(errno));" print always "Success". After the first correct receiving, the program print infinite times these two printf after recv and buffer is empty.
Client:
int main (int argc, char* argv[]) {
int ret, sd, i, len;
char buffer[1024];
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[1]));
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
for(;;) {
scanf("%s",buffer);
if(strcmp(buffer,"c")==0) {
sd = socket(AF_INET, SOCK_STREAM, 0);
ret = connect(sd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(ret<0) {
perror("Error ");
exit(1);
}
}
if(strcmp(buffer, "REQ\0")==0) {
ret = send(sd, buffer, sizeof(buffer), 0);
if(ret<0) {
perror("Error ");
exit(1);
}
ret = recv(sd, (void*)buffer, 7, 0);
if(ret<0) {
perror("Error ");
exit(1);
}
printf("Received: %s\n", buffer);
}
if(strcmp(buffer, "DEL\0")==0) {
ret = send(sd, buffer, sizeof(buffer), 0);
if(ret<0) {
perror("Error ");
exit(1);
}
close(sd);
return 0;
}
}
}
I am new to socket programming, so I'm sorry if this is a noob question.
I have a program in C for Linux, which connects two sockets from "server.c" to two "client.c"s with the help of fork(). It works just fine most of the time, but there are times when the second client gets stuck before the first recv() function. On these occasions, the server doesn't accept() the connection and I am confused as to what is truly happening and how I can fix it.
Since I don't know much about socket programming, any explanation could be useful.
Here is the codes for the server and the client:
server.c
int main(){
int server_socket, p1_socket, p2_socket;
int pid;
pid = fork();
if(pid<0)
printf("Fork failed.\n");
else if(pid==0){
//PLAYER 1
socket_creation_and_connection(&server_socket, &p1_socket);
connect_to_player(&p1_socket, 1);
}
else{
//PLAYER 2
socket_creation_and_connection(&server_socket, &p2_socket);
connect_to_player(&p2_socket, 2);
}
printf("Hello message sent from %d\n", pid);
return 0;
}
void connect_to_player(int *socket, int playerNo){
char buffer[256];
while(1){
send(*socket , (int *)&playerNo , sizeof(int) , 0);
recv(*socket, (int *)&buffer, 1024, 0);
printf("PlayerNo %d Message received from client %s\n", playerNo, buffer);
}
}
void socket_creation_and_connection (int *server_socket, int *new_socket){
struct sockaddr_in address;
int addrlen = sizeof(address);
printf("creating sth\n");
if ((*server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0){
perror("Failed to create socket.");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(*server_socket, (struct sockaddr *)&address, sizeof(address))<0){
perror("Failed to bind.");
exit(EXIT_FAILURE);
}
if (listen(*server_socket, 3)<0){
perror("Failed to listen.");
exit(EXIT_FAILURE);
}
if ((*new_socket = accept(*server_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0){
perror("Failed to accept.");
exit(EXIT_FAILURE);
}
printf("finished creating sth\n");
}
client.c
int main(){
int client_socket = 0;
char message[256];
socket_creation_and_connection(&client_socket);
int intbuf;
while(1){
recv(client_socket, (int *)&intbuf, sizeof(int), 0);
if(intbuf == 1)
printf("Received message from Player1\n");
else
printf("Received message from Player2\n");
printf("Type a string\n");
scanf("%s", message);
send(client_socket, message , strlen(message) , 0 );
sleep(1);
}
return 0;
}
void socket_creation_and_connection(int *client_socket){
struct sockaddr_in address;
if ((*client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_port = htons(PORT);
if (connect(*client_socket, (struct sockaddr *)&address, sizeof(address)) < 0)
{
printf("Connection Failed.\n");
exit(EXIT_FAILURE);
}
}
Edit: PORT is defined along with the libraries like this.
#define PORT 8080
Learning about TCP connections. Can anyone see why my accept() call is erroring with an "invalid argument"? I can't see what I am doing wrong. Thanks!
int main(int argc, char *argv[]) {
int sockfd, newfd;
struct sockaddr_in clientAddr;
unsigned int recvLen;
socklen_t addr_size;
fd_set read_set;
struct timeval tv;
// initialize the fd set
FD_ZERO(&read_set);
// prepare the address struct for the first client
bzero(&clientAddr,sizeof(clientAddr)); //zero the struct
clientAddr.sin_family = AF_INET; //address family (ipv4)
clientAddr.sin_port = htons(6001); //sets port to network byte order
clientAddr.sin_addr.s_addr = INADDR_ANY;
addr_size = sizeof(clientAddr);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stdout, "Cannot create socket for client 0.\n");
fprintf(stdout, "Terminating program\n\n");
exit(1);
} else {
fprintf(stdout, "Socket established for client 0\n");
}
if (bind(sockfd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) {
fprintf (stdout, "Binding failed for client 0\n\n");
perror("bind failed");
exit (1);
} else {
fprintf (stdout, "Binding successful for client 0\n");
}
// ERROR HAPPENS ON THE NEXT LINE
if ((newfd = accept(sockfd, (struct sockaddr *)&clientAddr, &addr_size)) < 0) {
fprintf(stdout, "Error accepting inbound data from client 0\n");
perror(" accept() failed");
exit(EXIT_FAILURE);
} else {
fprintf(stdout, "\tSuccessfully accepted inbound connection from client 0\n");
}
return 0;
}
A call to listen is missing after bind before accept.
I would initialize addr_size to sizeof(clientAddr) and clear clientAddr
I am writing a simple client and server program in C. I am able to send date from client to server. But, I am not able to send acknowledge from server to client.
/*******************udpserver.c*****************/
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc;
struct sockaddr_in serveraddr, clientaddr;
clientaddrlen = sizeof(clientaddr);
int serveraddrlen = sizeof(serveraddr);
char buffer[100];
char *bufptr = buffer;
int buflen = sizeof(buffer);
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("UDP server - socket() error");
exit(-1);
}
printf("UDP server - socket() is OK\n");
memset(&serveraddr, 0x00, serveraddrlen);
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(0);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if((rc = bind(sd, (struct sockaddr *)&serveraddr, serveraddrlen)) < 0) {
perror("UDP server - bind() error");
close(sd);
exit(-1);
}
int addr_len = sizeof(serveraddr);
if (getsockname(sd, (struct sockaddr *) &serveraddr, &addr_len)<0) {
perror("Error getting socket name.\n");
return -1;
}
printf("Using IP %s and port %d\n", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port));
printf("UDP server - Listening...\n");
rc = recvfrom(sd, bufptr, buflen, 0, (struct sockaddr *)&clientaddr, &clientaddrlen);
if(rc < 0) {
perror("UDP Server - recvfrom() error");
close(sd);
exit(-1);
}
printf("UDP Server received the following:\n \"%s\" message\n", bufptr);
printf("UDP Server replying to the UDP client...\n");
rc = sendto(sd, bufptr, buflen, 0, (struct sockaddr *)&clientaddr, clientaddrlen);
if(rc < 0) {
perror("UDP server - sendto() error");
close(sd);
exit(-1);
}
printf("UDP Server - sendto() is OK...\n");
close(sd);
exit(0);
}
My UDPClient program:
/****************udpclient.c********************/
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc;
struct sockaddr_in serveraddr, clientaddr;
int serveraddrlen = sizeof(serveraddr);
char server[255];
char buffer[100];
char *bufptr = buffer;
int buflen = sizeof(buffer);
struct hostent *hostp;
memset(buffer, 0x00, sizeof(buffer));
/* 36 characters + terminating NULL */
memcpy(buffer, "Hello! A client request message lol!", 37);
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("UDP Client - socket() error");
exit(-1);
}
else
printf("UDP Client - socket() is OK!\n");
if(argc != 3) {
/*Use default hostname or IP*/
printf("UDP Client - Usage <Server hostname or IP>\n");
exit(0);
}
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
hostp = gethostbyname(argv[1]);
if(hostp == (struct hostent *)NULL) {
printf("HOST NOT FOUND --> ");
printf("h_errno = %d\n", h_errno);
exit(-1);
}
else {
printf("UDP Client - gethostname() of the server is OK... \n");
printf("Connected to UDP server\n");
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
rc = sendto(sd, bufptr, buflen, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if(rc < 0) {
perror("UDP Client - sendto() error");
close(sd);
exit(-1);
}
else
printf("UDP Client - sendto() is OK!\n");
printf("Waiting a reply from UDP server...\n");
rc = recvfrom(sd, bufptr, buflen, 0, (struct sockaddr *)&serveraddr, &serveraddrlen);
if(rc < 0) {
perror("UDP Client - recvfrom() error");
close(sd);
exit(-1);
} else {
printf("UDP client received the following: \"%s\" message\n", bufptr);
}
close(sd);
exit(0);
}
When running the two programs, I am getting the following output:
UdpServer:
$ ./UdpServer
UDP server - socket() is OK
Using IP 0.0.0.0 and port 49932
UDP server - Listening...
UDP Server received the following:
"Hello! A client request message lol!" message
UDP Server replying to the UDP client...
UDP Server - sendto() is OK...
UdpClient:
$ ./UdpClient MyPC 49932
UDP Client - socket() is OK!
UDP Client - gethostname() of the server is OK...
Connected to UDP server
UDP Client - sendto() is OK!
Waiting a reply from UDP server...
UdpClient program is stuck at this point. Could anyone please explain what the problem is?
You might like to use select() to make the process wait until data is avaibale for reading:
...
{
fd_set rfds;
int retval;
FD_ZERO(&rfds);
FD_SET(sd, &rfds);
retval = select(sd+1, &rfds, NULL, NULL, NULL);
if (retval == -1)
perror("select()");
else
printf("Data is available for reading now.\n");
...
}
...
If the server and client are running on the same machine, give
$ ./UdpClient localhost 49932
instead of
$ ./UdpClient MyPC 49932
else
$ ./UdpClient <server-IP-address> 49932
Also in the server code,
clientaddrlen = sizeof(clientaddr);
should be
int clientaddrlen = sizeof(clientaddr);
But I guess that's just a copy-paste mistake.