-
July 14th, 2011, 11:11 PM
#1
Help on binding two sockets to two ports on ONE server [Socket Programming in UNIX]
Ok so this is what I have.
I have a separate code for both server and client.
Now, what I want to do is, enable the server to listen and accept connections on TWO OR MORE ports [say 5000 and 5340], thus, effectively creating two different "chat rooms". A bunch of clients communicate with each other and the server on the first port [5000], and a different bunch of clients communicate with each other, and the server on the other port [5340].
I have been able to get the server to listen and communicate on two different ports. But now, when I send a chat message from the client to the server, or from server to client, it doesn't display the message at the same time it receives it. Let me make this more clear. For example, I connect to the server on the first port. I then type two messages on the client, 'Hey' and 'Hurr Durr'. The server doesn't display anything. Now when I type 'Anyone there' on the server, it then displays 'Hey' and 'Hurr Durr' in quick succession. I think it's something to do with my for statements. I've tried to find out what exactly could the problem be for hours, and I'm drawing a blank.
Here is the server code :
-
July 14th, 2011, 11:14 PM
#2
Re: Help on binding two sockets to two ports on ONE server [Socket Programming in UNI
SERVER CODE :
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> //For read() and write()
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MSG_SIZE 80
#define MAX_CLIENTS 100
#define MYPORT 7400
void exitClient(int fd, fd_set *readfds, char fd_array[], int *num_clients)
{
int i;
close(fd);
FD_CLR(fd, readfds); //clear the leaving client from the set
for (i = 0; i < (*num_clients) - 1; i++)
{
if (fd_array[i] == fd)
{
break;
}
}
for (; i < (*num_clients) - 1; i++)
{
(fd_array[i]) = (fd_array[i + 1]);
}
(*num_clients)--;
}
int main(int argc, char *argv[])
{
int i=0;
int port1, port2;
int num_clients1 = 0, num_clients2 = 0;
int server_sockfd1,server_sockfd2, client_sockfd1, client_sockfd2;
struct sockaddr_in chatroom1, chatroom2;
int addresslen = sizeof(struct sockaddr_in);
int fd;
char fd_array1[MAX_CLIENTS], fd_array2[MAX_CLIENTS];
fd_set readfds1, readfds2, testfds1, testfds2, clientfds, readfds;
char msg[MSG_SIZE + 1];
char kb_msg[MSG_SIZE + 10];
int sockfd;
int result;
char hostname[MSG_SIZE];
struct hostent *hostinfo;
struct sockaddr_in address;
char alias[MSG_SIZE];
int clientid;
printf("\n*** Server program. (enter \"quit\" to close): \n");
fflush(stdout);
printf("Enter the two ports :");
scanf("%d %d",&port1,&port2);
/* Create and name a socket for the server */
server_sockfd1 = socket(AF_INET, SOCK_STREAM, 0);
chatroom1.sin_family = AF_INET;
chatroom1.sin_addr.s_addr = htonl(INADDR_ANY);
chatroom1.sin_port = htons(port1);
bind(server_sockfd1, (struct sockaddr *)&chatroom1, addresslen);
server_sockfd2 = socket(AF_INET, SOCK_STREAM, 0);
chatroom2.sin_family = AF_INET;
chatroom2.sin_addr.s_addr = htonl(INADDR_ANY);
chatroom2.sin_port = htons(port2);
bind(server_sockfd2, (struct sockaddr *)&chatroom2, addresslen);
/* Create a connection queue and initialize a file descriptor set */
listen(server_sockfd1, 1);
listen(server_sockfd2, 1);
FD_ZERO(&readfds1);
FD_ZERO(&readfds2);
FD_SET(server_sockfd1, &readfds1);
FD_SET(server_sockfd2, &readfds2);
FD_SET(0, &readfds1); /* Add keyboard to file descriptor set */
FD_SET(0, &readfds2); /* Add keyboard to file descriptor set */
/* Now wait for clients and requests */
while (1)
{
testfds1 = readfds1;
select(FD_SETSIZE, &testfds1, NULL, NULL, NULL);
testfds2 = readfds2;
select(FD_SETSIZE, &testfds2, NULL, NULL, NULL);
/* If there is activity, find which descriptor it's on using FD_ISSET */
for (fd = 0; fd < FD_SETSIZE; fd++)
{
if (FD_ISSET(fd, &testfds1)||FD_ISSET(fd, &testfds2))
{
if (fd == server_sockfd1)
{ /* Accept a new connection request */
client_sockfd1 = accept(server_sockfd1, NULL, NULL);
if (num_clients1 < MAX_CLIENTS)
{
FD_SET(client_sockfd1, &readfds1);
fd_array1[num_clients1]=client_sockfd1;
/*Client ID*/
printf("Client %d joined\n",num_clients1++);
fflush(stdout);
sprintf(msg,"M%2d",client_sockfd1);
/*write 2 byte clientID */
send(client_sockfd1,msg,strlen(msg),0);
}
else
{
sprintf(msg, "XSorry, too many clients. Try again later.\n");
write(client_sockfd1, msg, strlen(msg));
close(client_sockfd1);
}
}
else if (fd == server_sockfd2)
{ /* Accept a new connection request */
client_sockfd2 = accept(server_sockfd2, NULL, NULL);
if (num_clients2 < MAX_CLIENTS)
{
FD_SET(client_sockfd2, &readfds2);
fd_array2[num_clients2]=client_sockfd2;
/*Client ID*/
printf("Client %d joined\n",num_clients2++);
fflush(stdout);
sprintf(msg,"M%2d",client_sockfd2);
/*write 2 byte clientID */
send(client_sockfd2,msg,strlen(msg),0);
}
else
{
sprintf(msg, "XSorry, too many clients. Try again later.\n");
write(client_sockfd2, msg, strlen(msg));
close(client_sockfd2);
}
}
else if (fd == 0)
{ /* Process keyboard activity */
fgets(kb_msg, MSG_SIZE + 1, stdin);
if (strcmp(kb_msg, "quit\n")==0)
{
sprintf(msg, "XServer is shutting down.\n");
for (i = 0; i < num_clients1 ; i++)
{
write(fd_array1[i], msg, strlen(msg));
close(fd_array1[i]);
}
for (i = 0; i < num_clients2 ; i++)
{
write(fd_array2[i], msg, strlen(msg));
close(fd_array2[i]);
}
close(server_sockfd1);
close(server_sockfd2);
exit(0);
}
else
{
sprintf(msg, "M%s", kb_msg);
for (i = 0; i < num_clients1 ; i++)
{
write(fd_array1[i], msg, strlen(msg));
}
for (i = 0; i < num_clients2 ; i++)
{
write(fd_array2[i], msg, strlen(msg));
}
}
}
else if(FD_ISSET(fd, &testfds1))
{ /*Process Client specific activity*/
//read data from open socket
result = read(fd, msg, MSG_SIZE);
if(result==-1)
{
perror("read()");
}
else if(result>0)
{
/*read 2 bytes client id*/
sprintf(kb_msg,"M%2d",fd);
msg[result]='\0';
/*concatinate the client id with the client's message*/
strcat(kb_msg,msg+1);
/*print to other clients*/
for(i=0;i<num_clients1;i++)
{
if (fd_array1[i]!= fd) /*dont write msg to same client*/
write(fd_array1[i],kb_msg,strlen(kb_msg));
}
/*print to server*/
printf("%s",kb_msg+1);
/*Exit Client*/
if(msg[0] == 'X')
{
exitClient(fd,&readfds1, fd_array1,&num_clients1);
}
}
}
else if(FD_ISSET(fd, &testfds2))
{ /*Process Client specific activity*/
//read data from open socket
result = read(fd, msg, MSG_SIZE);
if(result==-1)
{
perror("read()");
}
else if(result>0)
{
/*read 2 bytes client id*/
sprintf(kb_msg,"M%2d",fd);
msg[result]='\0';
/*concatinate the client id with the client's message*/
strcat(kb_msg,msg+1);
/*print to other clients*/
for(i=0;i<num_clients2;i++)
{
if (fd_array2[i]!= fd) /*dont write msg to same client*/
write(fd_array2[i],kb_msg,strlen(kb_msg));
}
/*print to server*/
printf("%s",kb_msg+1);
/*Exit Client*/
if(msg[0] == 'X')
{
exitClient(fd,&readfds2, fd_array2,&num_clients2);
}
}
}
else if(!FD_ISSET(fd, &testfds1) && !FD_ISSET(fd, &testfds2))
{
/* A client is leaving */
exitClient(fd,&readfds1, fd_array1,&num_clients1);
}//if
}//if
}//for
}//while
}//main
And this is client code :
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> //For read() and write()
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MSG_SIZE 80
#define MAX_CLIENTS 100
#define MYPORT 7400
int main(int argc, char *argv[])
{
int port;
int num_clients = 0;
int fd;
fd_set readfds, testfds, clientfds;
char msg[MSG_SIZE + 1];
char kybd_msg[MSG_SIZE + 10];
int sockfd;
int result;
char hostname[MSG_SIZE];
struct hostent *hostinfo, *hp;
struct sockaddr_in address;
int clientid;
int auth;
int i;
char clientname[100];
size_t size;
time_t now;
struct tm *tm;
int newport;
char cmd[100];
printf("*** Client applet. (type |-quit-| to close): \n");
printf("\nPlease enter the port to connect to : ");
scanf("%i",&port);
printf("Please enter the address of the host to connect to : ");
scanf("%s",&hostname);
printf("\n");
fflush(stdout);
/* Create a socket for the client */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Name the socket, as agreed with the server */
hostinfo = gethostbyname(hostname); /* look for host's name */
address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
address.sin_family = AF_INET;
address.sin_port = htons(port);
/* Connect the socket to the server's socket */
if(connect(sockfd, (struct sockaddr *)&address,
sizeof(address)) < 0)
{
perror("Error in connecting.");
exit(1);
}
fflush(stdout);
FD_ZERO(&clientfds);
FD_SET(sockfd,&clientfds);
FD_SET(0,&clientfds);//stdin
printf("\nPlease enter your chat messages below.\n");
/* Now wait for messages from the server */
while (1)
{
testfds=clientfds;
select(FD_SETSIZE,&testfds,NULL,NULL,NULL);
for(fd=0;fd<FD_SETSIZE;fd++)
{
if(FD_ISSET(fd,&testfds))
{
if(fd == sockfd)
{ /*Accept data from open socket */
result = read(sockfd, msg, MSG_SIZE);
msg[result] = '\0';
now=time(NULL);
tm=localtime(&now);
printf("%d:%d : %s",tm->tm_hour,tm->tm_min,msg +1);
if (msg[0] == 'X')
{
close(sockfd);
exit(0);
}
}
else if(fd == 0)
{ /*process keyboard activiy*/
fgets(kybd_msg, MSG_SIZE+1, stdin);
if(strcmp(kybd_msg, "quit\n")==0)
{
sprintf(msg, "X Client is shutting down.\n");
write(sockfd, msg, strlen(msg));
close(sockfd); //close current client
exit(0); //end program
}
else
{
sprintf(msg, "M %s", kybd_msg);
write(sockfd, msg, strlen(msg));
}
}//elseif
}//if
}//for
}//while
}//main
-
July 15th, 2011, 09:13 AM
#3
Re: Help on binding two sockets to two ports on ONE server [Socket Programming in UNI
One problem might be your use of the select() calls.
Code:
testfds1 = readfds1;
select(FD_SETSIZE, &testfds1, NULL, NULL, NULL);
testfds2 = readfds2;
select(FD_SETSIZE, &testfds2, NULL, NULL, NULL);
When the first call returns, there might be some action on one of the socket in testfds1, but that isn't processed before the second call, which is now entered, returns. Now both FD sets can be evaluated.
I'd put all current sockets into one FD and remember the position, where the sockets for the chatroom 2 begin. That would give you one call to select. Maybe then your problem can be reduced, if not solved.
HTH,
Richard
-
July 16th, 2011, 03:11 AM
#4
Re: Help on binding two sockets to two ports on ONE server [Socket Programming in UNI
Hmm, how exactly would i specify where to start the fd's for the second socket in the FD_SET?
-
July 16th, 2011, 05:07 AM
#5
Re: Help on binding two sockets to two ports on ONE server [Socket Programming in UNI
Well, if you set 5 sockets for chatroom 1 via FD_SET, then you know that in
Code:
for (fd = 0; fd < FD_SETSIZE; fd++)
when to switch from chatroom 1 to 2, don't you?
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|