Can't get more than 3 active TCP connections in Mini-OS? - sockets

I'm writing an TCP server in Mini-OS(an operation system in xen), it can connect to multiple TCP clients. I wrote a simple code for handling multiple TCP clients , but there is an issue with the code. The issue is I can't get the server to connect more than three active connections. The 4th or more clients could not connect for unknown reasons. I looked around the forums and tried increasing the number limit for MEMP_NUM_TCP_PCB in opt.h (stubdom\lwip-x86_64\include\lwip\opt.h) and it didn't help either.
I'm running a TCP client on Ubuntu. Based on what I saw, the 4th client did seem connected, but an exception was thrown during the "write" function: "Resolver Error 0 (no error)"
How can I solve this problem?
//server code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 1234 // the port users will be connecting to
#define BACKLOG 2// how many pending connections queue will hold
#define BUF_SIZE 1024
int fd_A[BACKLOG]; // accepted connection fd
int conn_amount; // current connection amount
void showclient()
{
int i;
printf("-----> client amount: %d\n", conn_amount);
for (i = 0; i < BACKLOG; i++) {
printf("BACKLOG%d ---> fd = %d\n", i, fd_A[i]);
}
printf("\n\n");
}
int main(void)
{
sleep(1);
printf("start server\n");
int sock_fd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in server_addr; // server address information
struct sockaddr_in client_addr; // connector's address information
socklen_t sin_size;
int yes = 1;
char buf[BUF_SIZE];
int ret;
int i;
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
//if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
/*if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
//perror("setsockopt");
//exit(1);
}
if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1) {
printf("Set server socket nonblock failed\n");
exit(1);
}*/
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET; // host byte order
server_addr.sin_port = htons(MYPORT); // short, network byte order
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP
//memset(server_addr.sin_zero, '0', sizeof(server_addr.sin_zero));
if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(1);
}
printf("listen...\n");
if (listen(sock_fd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("listen port %d\n", MYPORT);
fd_set fdsr, wfds, efds;
int maxsock;
struct timeval tv;
conn_amount = 0;
sin_size = sizeof(client_addr);
maxsock = sock_fd;
while (1)
{
sleep(1); // it's necessary
// initialize file descriptor set
FD_ZERO(&fdsr);
FD_ZERO(&wfds);
//FD_ZERO(&efds);
FD_SET(sock_fd, &fdsr); // add fd
FD_SET(sock_fd, &wfds); // add fd
//FD_SET(sock_fd, &efds); // add fd
// timeout setting
tv.tv_sec = 30;
tv.tv_usec = 0;
// add active connection to fd set
for (i = 0; i < BACKLOG; i++) {
if (fd_A[i] != 0) {
FD_SET(fd_A[i], &fdsr);
}
}
//printf("before select!!!!!!!!!!!! ret = %d\n", ret);
if ((select(maxsock + 1, &fdsr, &wfds, (fd_set*) 0, (struct timeval*) 0)) < 0) {
perror("select");
break;
}
// check every fd in the set
for (i = 0; i < conn_amount; i++)
{
if (FD_ISSET(fd_A[i], &fdsr)) // check which fd is ready
{
ret = recv(fd_A[i], buf, sizeof(buf), 0);
if (ret <= 0)
{ // client close
printf("ret : %d and client[%d] close\n", ret, i);
close(fd_A[i]);
FD_CLR(fd_A[i], &fdsr); // delete fd
fd_A[i] = 0;
conn_amount--;
}
else
{ // receive data
if (ret < BUF_SIZE)
memset(&buf[ret], '\0', 1); // add NULL('/0')
printf("client[%d] send:%s\n", i, buf);
}
}
}
// check whether a new connection comes
if (FD_ISSET(sock_fd, &fdsr)) // accept new connection
{
new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
if (new_fd <= 0)
{
perror("accept");
continue;
}
// add to fd queue
if (conn_amount < BACKLOG)
{
fd_A[conn_amount++] = new_fd;
printf("------> new connection client[%d] %s:%d\n", conn_amount,
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (new_fd > maxsock) // update the maxsock fd for select function
maxsock = new_fd;
}
else
{
printf("max connections arrive, exit\n");
send(new_fd, "bye", 4, 0);
close(new_fd);
break;
}
}
//showclient();
}
// close other connections
for (i = 0; i < BACKLOG; i++)
{
if (fd_A[i] != 0)
{
close(fd_A[i]);
}
}
exit(0);
}
//client code
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <malloc.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define RES_LENGTH 10240
int connect_socket(char * server,int serverPort);
int send_msg(int sockfd,char * sendBuff);
char * recv_msg(int sockfd);
int close_socket(int sockfd);
int main(int argc, char ** argv)
{
int sockfd[1024] = {0};
char sendMsg[30]="zhangchengfei\r\n\r";
char* res;
int port = 1234;
char ip[128] = {0};
strncpy(ip, "10.107.19.62", 128);
if(argc > 2)
{
strncpy(ip, argv[1], 128);
port = atoi(argv[2]);
printf("Input IP: %s, port : %d\n", ip, port);
}
else if(argc > 1)
{
//port = atoi(argv[1]);
//printf("Input port : %d\n", port);
//
int num_client = atoi(argv[1]);
int i = 0;
for (i = 0; i <= num_client; i++) {
printf("start connect %d\n", i + 1);
sockfd[i]=connect_socket(ip, port);
printf("connect %d OK\n", i + 1);
getchar();
}
for (i = 0; i <= num_client; i++) {
send_msg(sockfd[i], sendMsg);
/* res=recv_msg(sockfd); */
printf("client %d send msg = %s\n", i + 1, sendMsg);
//printf(res);
//free(res);
getchar();
}
for (i = 0; i <= num_client; i++) {
close_socket(sockfd[i]);
printf("close socket %d\n", i + 1);
}
}
return 0;
}
int connect_socket(char * server,int serverPort){
int sockfd=0;
struct sockaddr_in addr;
struct hostent * phost;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
herror("Init socket error!");
return -1;
}
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(serverPort);
addr.sin_addr.s_addr = inet_addr(server);
if(addr.sin_addr.s_addr == INADDR_NONE){
phost = (struct hostent*)gethostbyname(server);
if(phost==NULL){
herror("Init socket s_addr error!");
return -1;
}
addr.sin_addr.s_addr =((struct in_addr*)phost->h_addr)->s_addr;
}
if(connect(sockfd,(struct sockaddr*)&addr, sizeof(addr))<0)
{
perror("Connect server fail!");
return -1;
}
else
return sockfd;
}
int send_msg(int sockfd,char * sendBuff)
{
int sendSize=0;
if((sendSize=send(sockfd,sendBuff,strlen(sendBuff),0))<=0){
herror("Send msg error!");
return -1;
}else
return sendSize;
}
char* recv_msg(int sockfd){
char * response;
int flag=0,recLenth=0;
response=(char *)malloc(RES_LENGTH);
memset(response,0,RES_LENGTH);
for(flag=0;;)
{
printf("======recv data:\n");
if(( recLenth=recv(sockfd,response+flag,RES_LENGTH-flag,0))==-1 )
{
free(response);
printf("Return value : %d\n", recLenth);
perror("Recv msg error : ");
return NULL;
}
else if(recLenth==0)
break;
else
{
printf("%d char recieved data : %s.\n", recLenth, response+flag);
flag+=recLenth;
recLenth=0;
}
}
printf("Return value : %d\n", recLenth);
response[flag]='0';
return response;
}
int close_socket(int sockfd)
{
close(sockfd);
return 0;
}

I have solved this problem caused by a Makefile bug in ./stubdom, after executing make crossclean , I found the .o files still existed in lwip-x86_64 folder. So I add a command find . -name "*.o" | xargs rm -f in Makefile and then anything is OK.
The reason is that lwip configure is given by the macro definition, macro definition have been replaced at the pre-compilation stage, so if I modify the lwip configure and did not delete the .o files, there is no effect. Following is the macro definitions I have modified in opt.h.
MEMP_NUM_TCP_PCB 100
MEMP_NUM_TCP_PCB_LISTEN 100
MEMP_NUM_NETCONN 100
Now the server can break through the connection limitations and more than 3 active TCP connections can be established, but sad that we have encountered another problem, the server side only can receive 61 clients of the connection requests. If exceeding the clients number, server side error will be reported as follows:
ASSERTION FAILED: mbox->reader != mbox->writer at lwip-arch.c:124.
Do_exit called!
base is 0x29fe78 caller is 0x4d49d
base is 0x29fe98 caller is 0x5a05a
base is 0x29fec8 caller is 0x5a153
base is 0x29fef8 caller is 0x634a1
base is 0x29ff28 caller is 0x65074
base is 0x29ff78 caller is 0x5d0dd
base is 0x29ffc8 caller is 0x59822
base is 0x29ffe8 caller is 0x33da
How can I solve the above problem?

Related

I am not able to send data to all clients from a single server

I am using a for loop on the server-side to send data to all clients received from a single client. But it is unable to send to all clients. Instead, it just sends data to the only client who has sent the data. And also it is not printing the here printf line on the server console.
for(int j=0;j<i;j++){
printf("here");
send(fds[j], buffer, strlen(buffer), 0);
}
My server-side code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 9999
int main(int argc, char* argv[]){
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
char lastchar = 'a';
socklen_t addr_size;
char buffer[1024];
pid_t childpid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Server Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("[-]Error in binding.\n");
exit(1);
}
printf("[+]Bind to port %d\n", 4444);
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
printf("[-]Error in binding.\n");
}
int fds[10];
int i = 0;
while(1){
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
fds[i++] = newSocket;
if(newSocket < 0){
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
if((childpid = fork()) == 0){
close(sockfd);
while(1){
recv(newSocket, buffer, 1024, 0);
if(strcmp(buffer, ":exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
}else{
if(buffer[0]==lastchar){
lastchar = buffer[strlen(buffer)-1];
bzero(buffer, sizeof(buffer));
strcpy(buffer, "Correct!");
}else{
bzero(buffer, sizeof(buffer));
strcpy(buffer, "Wrong!");
}
for(int j=0;j<i;j++){
printf("here");
send(fds[j], buffer, strlen(buffer), 0);
}
bzero(buffer, sizeof(buffer));
}
}
}
}
close(newSocket);
return 0;
}
My Client-side code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 9999
int main(){
int clientSocket, ret;
struct sockaddr_in serverAddr;
char buffer[1024];
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Client Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Connected to Server.\n");
while(1){
printf("Client: \t");
scanf("%s", &buffer[0]);
send(clientSocket, buffer, strlen(buffer), 0);
if(strcmp(buffer, ":exit") == 0){
close(clientSocket);
printf("[-]Disconnected from server.\n");
exit(1);
}
if(recv(clientSocket, buffer, 1024, 0) < 0){
printf("[-]Error in receiving data.\n");
}else{
printf("Server: \t%s\n", buffer);
}
}
return 0;
}
If I change my server code to the following can anybody tell me how to reply to all clients?
//Example code: A simple server side code, which echos back the received message.
//Handle multiple socket connections with select and fd_set on Linux
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h>
#include <errno.h>
#include <unistd.h> //close
#include <arpa/inet.h> //close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros
#define TRUE 1
#define FALSE 0
#define PORT 8888
int main(int argc , char *argv[])
{
int opt = TRUE;
int master_socket , addrlen , new_socket , client_socket[30] ,
max_clients = 30 , activity, i , valread , sd;
int max_sd;
struct sockaddr_in address;
char buffer[1025]; //data buffer of 1K
//set of socket descriptors
fd_set readfds;
//a message
char *message = "ECHO Daemon v1.0 \r\n";
//initialise all client_socket[] to 0 so not checked
for (i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
//create a master socket
if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
//set master socket to allow multiple connections ,
//this is just a good habit, it will work without this
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
//type of socket created
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
//bind the socket to localhost port 8888
if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("Listener on port %d \n", PORT);
//try to specify maximum of 3 pending connections for the master socket
if (listen(master_socket, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
//accept the incoming connection
addrlen = sizeof(address);
puts("Waiting for connections ...");
while(TRUE)
{
//clear the socket set
FD_ZERO(&readfds);
//add master socket to set
FD_SET(master_socket, &readfds);
max_sd = master_socket;
//add child sockets to set
for ( i = 0 ; i < max_clients ; i++)
{
//socket descriptor
sd = client_socket[i];
//if valid socket descriptor then add to read list
if(sd > 0)
FD_SET( sd , &readfds);
//highest file descriptor number, need it for the select function
if(sd > max_sd)
max_sd = sd;
}
//wait for an activity on one of the sockets , timeout is NULL ,
//so wait indefinitely
activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL);
if ((activity < 0) && (errno!=EINTR))
{
printf("select error");
}
//If something happened on the master socket ,
//then its an incoming connection
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket,
(struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
//inform user of socket number - used in send and receive commands
printf("New connection , socket fd is %d , ip is : %s , port : %d
\n" , new_socket , inet_ntoa(address.sin_addr) , ntohs
(address.sin_port));
//send new connection greeting message
if( send(new_socket, message, strlen(message), 0) != strlen(message) )
{
perror("send");
}
puts("Welcome message sent successfully");
//add new socket to array of sockets
for (i = 0; i < max_clients; i++)
{
//if position is empty
if( client_socket[i] == 0 )
{
client_socket[i] = new_socket;
printf("Adding to list of sockets as %d\n" , i);
break;
}
}
}
//else its some IO operation on some other socket
for (i = 0; i < max_clients; i++)
{
sd = client_socket[i];
if (FD_ISSET( sd , &readfds))
{
//Check if it was for closing , and also read the
//incoming message
if ((valread = read( sd , buffer, 1024)) == 0)
{
//Somebody disconnected , get his details and print
getpeername(sd , (struct sockaddr*)&address , \
(socklen_t*)&addrlen);
printf("Host disconnected , ip %s , port %d \n" ,
inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
close( sd );
client_socket[i] = 0;
}
//Echo back the message that came in
else
{
//set the string terminating NULL byte on the end
//of the data read
buffer[valread] = '\0';
send(sd , buffer , strlen(buffer) , 0 );
}
}
}
}
return 0;
}
When you call fork(), the child process effectively receives its own separate copy of the parent process's address-space. Since the child process's address-space is separate and independent from that of its parent process, any subsequent changes to variables in the parent process's address space will not be seen by the child process.
Since your server is calling fork() for each new TCP connection that is received, that means that each new TCP connection is getting its own address-space that includes it and any already-accepted sockets, but will never include any sockets that are accepted on the server after that client's process was spawned. That is likely why you aren't seeing all the file descriptors you expect in your fds array, when you iterate over it calling send().
My advice is to simply get rid of the fork() call. If you want to keep (and iterate over) a list of all connected clients' file-descriptors, then its much simpler to use a single-process model rather than a process-per-client model. If you need to react to incoming input data from any of the clients, you can use non-blocking I/O and block instead inside select() or poll() until one of the file descriptors in your list has incoming data ready for you to read.

The client sents message to the server and shows error couldn't sent, whats the problem in the program

The client program:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define LEN 256
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *result, *rp;
int sock, s, n, r;
char message[256] , receive[1024];
int msglen, recvlen;
if (argc < 3)
{
fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* streaming socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
s = getaddrinfo(argv[1], argv[2], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully connect(2).
If socket(2) (or connect(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1)
continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sock);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
/* Send remaining command-line arguments as separate
datagrams, and read responses from server */
while(1)
{
bzero(message, LEN );
fgets(message, LEN, stdin);
printf("The server sent: %s\n",message);
n = send(sock, message, strlen(message), 0);
{
fprintf(stderr, "Could not send\n");
exit(EXIT_FAILURE);
}
bzero(message, 255);
n = recv(sock, message, LEN, 0);
if (n < 0)
{
fprintf(stderr, "Could not receive\n");
exit(EXIT_FAILURE);
}
printf("The client received: %s\n", message);
int i = strncmp("Exit", receive, 4);
if(i == 0)
break;
}
return 0;
}
The server program:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define LEN 256
int main(int argc, char *argv[]) {
struct addrinfo hints;
struct addrinfo *result, *rp;
struct sockaddr_in storage;
int sock, s,l,a,n;
char receive[LEN], response[1024];
int recvlen = strlen(receive);
pid_t childpid;
if (argc != 2)
{
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
hints.ai_flags = 0; /* For wildcard IP address */
hints.ai_protocol = 0; /* Any protocol */
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
s = getaddrinfo(NULL, argv[1], &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
/* getaddrinfo() returns a list of address structures.
Try each address until we successfully bind(2).
If socket(2) (or bind(2)) fails, we (close the socket
and) try the next address. */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sock == -1)
continue;
if (bind(sock, rp->ai_addr, rp->ai_addrlen) == 0)
break; /* Success */
close(sock);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not bind\n");
exit(EXIT_FAILURE);
}
l = listen(sock, 5);
if(l != 0)
{
fprintf(stderr, "error in listening\n");
exit(EXIT_FAILURE);
}
socklen_t str_storage = sizeof(storage);
a = accept(sock, (struct sockaddr*)&storage, &str_storage);
if(a < 0)
{
fprintf(stderr, "the acceptance is not done\n");
exit(EXIT_FAILURE);
}
while(1)
{
bzero(receive, LEN);
n = recv(a, receive, LEN , 0);
if(n < 0)
{
fprintf(stderr, "error in reading\n");
exit(EXIT_FAILURE);
}
printf("The client message: %s\n ", receive);
bzero(receive, LEN);
fgets(receive, LEN, stdin);
n = send(a, receive, recvlen, 0);
if(n < 0)
{
fprintf(stderr, "error in replying\n");
exit(EXIT_FAILURE);
}
int i = strncmp("Exit", receive, 4);
if(i == 0)
break;
printf("The server message: %s\n", receive);
}
close(a);
return 0;
}
linux output both sides:
$ ./client localhost 5690
deeeksha hey
The server sent: deeeksha hey
Could not send
server output:
$ ./server 5690
The client message: deeeksha hey
n = send(sock, message, strlen(message), 0);
{
fprintf(stderr, "Could not send\n");
exit(EXIT_FAILURE);
}
Your client is executing this block no matter if the send was successful or not. It looks like you've forgot to check for if (n<0) but instead just had a block without any condition. Likely a case of copy & paste from somewhere else in your code by forgetting to copy the first line.

Is there a connection limitation using LWIP?

I'm writing a TCP server using Lwip Protocol, normally the server can connect to multiple TCP clients. However I have a problem , the server can't connect more than three active connections. The 4th or more clients could not connect for unknown reasons. I looked around the forums and tried increasing the number limit for MEMP_NUM_TCP_PCB in opt.h (lwip-x86_64\include\lwip\opt.h) but it didn't help.
Following is my code, and my questions is whether is there a max connection limitation using LWIP ? Maximum number of connections is 3 or more?
//server code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 1234 // the port users will be connecting to
#define BACKLOG 2// how many pending connections queue will hold
#define BUF_SIZE 1024
int fd_A[BACKLOG]; // accepted connection fd
int conn_amount; // current connection amount
void showclient()
{
int i;
printf("-----> client amount: %d\n", conn_amount);
for (i = 0; i < BACKLOG; i++) {
printf("BACKLOG%d ---> fd = %d\n", i, fd_A[i]);
}
printf("\n\n");
}
int main(void)
{
sleep(1);
printf("start server\n");
int sock_fd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in server_addr; // server address information
struct sockaddr_in client_addr; // connector's address information
socklen_t sin_size;
int yes = 1;
char buf[BUF_SIZE];
int ret;
int i;
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
//if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
/*if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
//perror("setsockopt");
//exit(1);
}
if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1) {
printf("Set server socket nonblock failed\n");
exit(1);
}*/
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET; // host byte order
server_addr.sin_port = htons(MYPORT); // short, network byte order
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP
//memset(server_addr.sin_zero, '0', sizeof(server_addr.sin_zero));
if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(1);
}
printf("listen...\n");
if (listen(sock_fd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("listen port %d\n", MYPORT);
fd_set fdsr, wfds, efds;
int maxsock;
struct timeval tv;
conn_amount = 0;
sin_size = sizeof(client_addr);
maxsock = sock_fd;
while (1)
{
sleep(1); // it's necessary
// initialize file descriptor set
FD_ZERO(&fdsr);
FD_ZERO(&wfds);
//FD_ZERO(&efds);
FD_SET(sock_fd, &fdsr); // add fd
FD_SET(sock_fd, &wfds); // add fd
//FD_SET(sock_fd, &efds); // add fd
// timeout setting
tv.tv_sec = 30;
tv.tv_usec = 0;
// add active connection to fd set
for (i = 0; i < BACKLOG; i++) {
if (fd_A[i] != 0) {
FD_SET(fd_A[i], &fdsr);
}
}
//printf("before select!!!!!!!!!!!! ret = %d\n", ret);
if ((select(maxsock + 1, &fdsr, &wfds, (fd_set*) 0, (struct timeval*) 0)) < 0) {
perror("select");
break;
}
// check every fd in the set
for (i = 0; i < conn_amount; i++)
{
if (FD_ISSET(fd_A[i], &fdsr)) // check which fd is ready
{
ret = recv(fd_A[i], buf, sizeof(buf), 0);
if (ret <= 0)
{ // client close
printf("ret : %d and client[%d] close\n", ret, i);
close(fd_A[i]);
FD_CLR(fd_A[i], &fdsr); // delete fd
fd_A[i] = 0;
conn_amount--;
}
else
{ // receive data
if (ret < BUF_SIZE)
memset(&buf[ret], '\0', 1); // add NULL('/0')
printf("client[%d] send:%s\n", i, buf);
}
}
}
// check whether a new connection comes
if (FD_ISSET(sock_fd, &fdsr)) // accept new connection
{
new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
if (new_fd <= 0)
{
perror("accept");
continue;
}
// add to fd queue
if (conn_amount < BACKLOG)
{
fd_A[conn_amount++] = new_fd;
printf("------> new connection client[%d] %s:%d\n", conn_amount,
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (new_fd > maxsock) // update the maxsock fd for select function
maxsock = new_fd;
}
else
{
printf("max connections arrive, exit\n");
send(new_fd, "bye", 4, 0);
close(new_fd);
break;
}
}
//showclient();
}
// close other connections
for (i = 0; i < BACKLOG; i++)
{
if (fd_A[i] != 0)
{
close(fd_A[i]);
}
}
exit(0);
}
//client code
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <malloc.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define RES_LENGTH 10240
int connect_socket(char * server,int serverPort);
int send_msg(int sockfd,char * sendBuff);
char * recv_msg(int sockfd);
int close_socket(int sockfd);
int main(int argc, char ** argv)
{
int sockfd[1024] = {0};
char sendMsg[30]="zhangchengfei\r\n\r";
char* res;
int port = 1234;
char ip[128] = {0};
strncpy(ip, "10.107.19.62", 128);
if(argc > 2)
{
strncpy(ip, argv[1], 128);
port = atoi(argv[2]);
printf("Input IP: %s, port : %d\n", ip, port);
}
else if(argc > 1)
{
//port = atoi(argv[1]);
//printf("Input port : %d\n", port);
//
int num_client = atoi(argv[1]);
int i = 0;
for (i = 0; i <= num_client; i++) {
printf("start connect %d\n", i + 1);
sockfd[i]=connect_socket(ip, port);
printf("connect %d OK\n", i + 1);
getchar();
}
for (i = 0; i <= num_client; i++) {
send_msg(sockfd[i], sendMsg);
/* res=recv_msg(sockfd); */
printf("client %d send msg = %s\n", i + 1, sendMsg);
//printf(res);
//free(res);
getchar();
}
for (i = 0; i <= num_client; i++) {
close_socket(sockfd[i]);
printf("close socket %d\n", i + 1);
}
}
return 0;
}
int connect_socket(char * server,int serverPort){
int sockfd=0;
struct sockaddr_in addr;
struct hostent * phost;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
herror("Init socket error!");
return -1;
}
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(serverPort);
addr.sin_addr.s_addr = inet_addr(server);
if(addr.sin_addr.s_addr == INADDR_NONE){
phost = (struct hostent*)gethostbyname(server);
if(phost==NULL){
herror("Init socket s_addr error!");
return -1;
}
addr.sin_addr.s_addr =((struct in_addr*)phost->h_addr)->s_addr;
}
if(connect(sockfd,(struct sockaddr*)&addr, sizeof(addr))<0)
{
perror("Connect server fail!");
return -1;
}
else
return sockfd;
}
int send_msg(int sockfd,char * sendBuff)
{
int sendSize=0;
if((sendSize=send(sockfd,sendBuff,strlen(sendBuff),0))<=0){
herror("Send msg error!");
return -1;
}else
return sendSize;
}
char* recv_msg(int sockfd){
char * response;
int flag=0,recLenth=0;
response=(char *)malloc(RES_LENGTH);
memset(response,0,RES_LENGTH);
for(flag=0;;)
{
printf("======recv data:\n");
if(( recLenth=recv(sockfd,response+flag,RES_LENGTH-flag,0))==-1 )
{
free(response);
printf("Return value : %d\n", recLenth);
perror("Recv msg error : ");
return NULL;
}
else if(recLenth==0)
break;
else
{
printf("%d char recieved data : %s.\n", recLenth, response+flag);
flag+=recLenth;
recLenth=0;
}
}
printf("Return value : %d\n", recLenth);
response[flag]='0';
return response;
}
int close_socket(int sockfd)
{
close(sockfd);
return 0;
}
I have solved this problem caused by a Makefile bug in ./stubdom, after executing make crossclean , I found the .o files still existed in lwip-x86_64 folder. So I add a command find . -name "*.o" | xargs rm -f in Makefile and then anything is OK.
The reason is that lwip configure is given by the macro definition, macro definition have been replaced at the pre-compilation stage, so if I modify the lwip configure and did not delete the .o files, there is no effect. Following is the macro definitions I have modified in opt.h.
MEMP_NUM_TCP_PCB 100
MEMP_NUM_TCP_PCB_LISTEN 100
MEMP_NUM_NETCONN 100
Now the server can break through the connection limitations and more than 3 active TCP connections can be established.

handling multiple clients using select

As i already asked similar questions but didn't get a solution. Hence i put this problem again with the whole code. Please tell me how can i acheive this goal
1) i have a client which sends to mainserver (127.0.0.1) a message and main server forwards it to server2 (127.0.0.2)
2) Server2 sends a message to the mainserver and mainserver forwards it to client.
Problem 1) : Although i receive the datas from client but they are not sent to server2.
Problem 2) :I dont receive any data from server2
//SERVER
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>//use select() for multiplexing
#include <sys/fcntl.h> // for non-blocking
#define MAX_LENGTH 100000
#define PORT 1901
/* Select() params
* int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
* FD_SET(int fd, fd_set *set);
* FD_CLR(int fd, fd_set *set);
* FD_ISSET(int fd, fd_set *set);
* FD_ZERO(fd_set *set);
*/
void error(char *message)
{
perror(message);
exit(1);
}
int main()
{
// select parameters declared
fd_set original_socket;
fd_set original_stdin;
fd_set readfds;
fd_set writefds;
struct timeval tv;
int numfd, numfd2;
// socket parameters declared
int socket_fd_ob, socket_fd_hm;
int bytes_read, bytes_sent;
char address_length, address_length2;
char recieve_data[MAX_LENGTH];
char send_data[MAX_LENGTH];
struct sockaddr_in server_address_ob, server_address_hm, client_address;
int z = 0;
//Socket creation done separately for both OBCU and HM communications
if ((socket_fd_ob = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
if ((socket_fd_hm = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
fcntl(socket_fd_ob, F_SETFL, O_NONBLOCK); //set socket to non-blocking
fcntl(socket_fd_hm, F_SETFL, O_NONBLOCK); //set socket to non-blocking
// clear the set ahead of time
FD_ZERO(&original_socket);
FD_ZERO(&original_stdin);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
// add our descriptors to the set (0 - stands for STDIN)
FD_SET(socket_fd_ob, &original_socket);//instead of 0 put socket_fd_ob
FD_SET(socket_fd_ob, &readfds);
FD_SET(0,&original_stdin);
FD_SET(0, &writefds);
// the n param in select()
numfd = socket_fd_ob + 1;
numfd2 = socket_fd_hm + 1;
// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
tv.tv_sec = 0.7;
tv.tv_usec = 500000;
server_address_ob.sin_family = AF_INET;
server_address_ob.sin_port = htons(1901);
server_address_ob.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(server_address_ob.sin_zero),sizeof(server_address_ob));
server_address_hm.sin_family = AF_INET;
server_address_hm.sin_port = htons(1901);
server_address_hm.sin_addr.s_addr = inet_addr("127.0.0.2");
bzero(&(server_address_ob.sin_zero),sizeof(server_address_hm));
// Bind socket to the particular addresses
if (bind(socket_fd_ob,(struct sockaddr *)&server_address_ob, sizeof(struct sockaddr)) == -1)
{
error("bind()");
}
if (bind(socket_fd_hm,(struct sockaddr *)&server_address_hm, sizeof(struct sockaddr)) == -1)
{
error("bind()");
}
address_length = sizeof(struct sockaddr);
address_length2 = sizeof(struct sockaddr);
printf("\nMain server waiting for client to respond...\n");
fflush(stdout);
while (1)
{
readfds = original_socket;
writefds = original_stdin;//problem
int recieve = select(numfd, &readfds, &writefds,/*NULL,*/ NULL, &tv);
int sent = select(numfd2, &readfds, &writefds,/*NULL,*/ NULL, &tv);
if (recieve == -1 || sent == -1)
{
perror("select"); // error occurred in select()
}
else if (recieve == 0 || sent == 0)
{
printf("Timeout occurred! No data after 1.5 seconds.\n");
}
else
{
// one or both of the descriptors have data
if (FD_ISSET(socket_fd_ob, &readfds)) //if set to read
{
FD_CLR(socket_fd_ob, &readfds);
if (bytes_read = recvfrom(socket_fd_ob,recieve_data,MAX_LENGTH,0,(struct sockaddr *)&server_address_ob, &address_length)>0)
{
for (z = 0; z < bytes_read; ++z) {
FD_ISSET(socket_fd_hm, &writefds);
FD_CLR(socket_fd_hm, &writefds);
//recvfrom speech recognition client and decide what to send to HM accordingly..
send_data[bytes_read] = recieve_data[bytes_read];
//block call, will wait till client enters something, before proceeding
//send the corresponding to HM
bytes_sent = sendto(socket_fd_hm,send_data,strlen(send_data)+1,0,(struct sockaddr *)&server_address_hm, &address_length2);
fflush(stdout);
}
// 02x, #x,X
printf("\n(%s , %d) rcvd: %s\n",inet_ntoa(server_address_ob.sin_addr),ntohs(server_address_ob.sin_port),recieve_data);
printf("\n(%s , %d) sent: %s\n",inet_ntoa(server_address_hm.sin_addr),ntohs(server_address_hm.sin_port),send_data);
recieve_data[bytes_read] = '\0'; //add null to the end of the buffer
send_data[bytes_read] = '\0'; //add null to the end of the buffer
}
else if (bytes_read = recvfrom(socket_fd_hm,recieve_data,MAX_LENGTH,0,(struct sockaddr *)&server_address_hm, &address_length)>0)
{
for (z = 0; z < bytes_read; ++z) {
FD_ISSET(socket_fd_ob, &writefds);
FD_CLR(socket_fd_ob, &writefds);
send_data[bytes_read] = recieve_data[bytes_read];
//block call, will wait till client enters something, before proceeding
//send the corresponding to HM
bytes_sent = sendto(socket_fd_ob,send_data,strlen(send_data)+1,0,(struct sockaddr *)&server_address_ob, &address_length2);
fflush(stdout);
}
// 02x, #x,X
printf("\n(%s , %d) rcvd: %s\n",inet_ntoa(server_address_hm.sin_addr),ntohs(server_address_hm.sin_port),recieve_data);
printf("\n(%s , %d) sent: %s\n",inet_ntoa(server_address_ob.sin_addr),ntohs(server_address_ob.sin_port),send_data);
recieve_data[bytes_read] = '\0'; //add null to the end of the buffer
send_data[bytes_read] = '\0'; //add null to the end of the buffer
}
else
{
printf("error noted");
}
} //end if set to read
} //end else
}//end while
close (socket_fd_ob);
close (socket_fd_hm);
return 0;
}
Please suggest me with code samples. i am new to this topic and didn't have a broad view yet.
Thanks

How to use select() in UDP Sockets to read and write from client to server

I'm trying to make a chat application using sockets, and I want them both to be able to write and read simultaneously. So I did some research and found that I/O multiplexing like select() will fix this problem. But I still have one problem. After I compile it and run it, one of the two programs doesn't receive the message 'till after one responds. So for example, the server sends a message to the client right? Then the client won't see the message until AFTER the client responds. Below you can find an example of this as well as the source code.
Client: hi
Server: hello
Client said "hi"
And the same for client etc
//SERVER
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>//use select() for multiplexing
#include <sys/fcntl.h> // for non-blocking
#define MAX_LENGTH 1024
/* Select() params
* int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
* FD_SET(int fd, fd_set *set);
* FD_CLR(int fd, fd_set *set);
* FD_ISSET(int fd, fd_set *set);
* FD_ZERO(fd_set *set);
*/
void error(char *message)
{
perror(message);
exit(1);
}
int main()
{
fd_set original_socket;
fd_set original_stdin;
fd_set readfds;
fd_set writefds;
struct timeval tv;
int numfd;
int socket_fd, bytes_read;
unsigned int address_length;
char recieve_data[MAX_LENGTH],send_data[MAX_LENGTH];
struct sockaddr_in server_address , client_address;
if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
int flags = fcntl(socket_fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(socket_fd, F_SETFL, flags);
//fcntl(socket_fd, F_SETFL, O_NONBLOCK); //set socket to non-blocking
// clear the set ahead of time
FD_ZERO(&original_socket);
FD_ZERO(&original_stdin);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
// add our descriptors to the set (0 - stands for STDIN)
FD_SET(socket_fd, &original_socket);//instead of 0 put socket_fd
FD_SET(socket_fd, &readfds);
FD_SET(0,&original_stdin);
FD_SET(0, &writefds);
// since we got s2 second, it's the "greater", so we use that for
// the n param in select()
numfd = socket_fd + 1;
// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
tv.tv_sec = 10;
tv.tv_usec = 500000;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(5000);
server_address.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_address.sin_zero),8);
if (bind(socket_fd,(struct sockaddr *)&server_address, sizeof(struct sockaddr)) == -1)
{
error("bind()");
}
address_length = sizeof(struct sockaddr);
printf("\nUDP_Server Waiting for client to respond...\n");
fflush(stdout);
printf("Type (q or Q) at anytime to quit\n");
while (1)
{
readfds = original_socket;
writefds = original_stdin;//problem
int recieve = select(numfd, &readfds, &writefds,/*NULL,*/ NULL, &tv);
if (recieve == -1)
{
perror("select"); // error occurred in select()
}
else if (recieve == 0)
{
printf("Timeout occurred! No data after 10.5 seconds.\n");
}
else
{
// one or both of the descriptors have data
if (FD_ISSET(socket_fd, &readfds)) //if set to read
{
FD_CLR(socket_fd, &readfds);
bytes_read = recvfrom(socket_fd,recieve_data,MAX_LENGTH,0,(struct sockaddr *)&client_address, &address_length); //block call, will wait till client enters something, before proceeding
recieve_data[bytes_read] = '\0'; //add null to the end of the buffer
if((strcmp(recieve_data , "q") == 0) || (strcmp(recieve_data , "Q") == 0)) { //if client quit, then quit also
printf("\nClient has exited the chat.\n");
break;
}
printf("\n(%s , %d) said: %s\n",inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port),recieve_data);
}
else if (FD_ISSET(/*socket_fd*/0, &writefds)) //if set to write
//else
{
FD_CLR(0, &writefds);
printf("SERVER: ");
fgets (send_data, MAX_LENGTH, stdin); //input the name with a size limit of MAX_LENGTH
if ((strlen(send_data)>0) && (send_data[strlen (send_data) - 1] == '\n')) //if there is a trailing \n, remove it
{
send_data[strlen (send_data) - 1] = '\0';
}
if ((strcmp(send_data , "q") == 0) || (strcmp(send_data , "Q") == 0)) { //if user enters q, then quit
sendto(socket_fd,send_data,strlen(send_data),0,(struct sockaddr *)&client_address, sizeof(struct sockaddr));
break;
}
sendto(socket_fd,send_data,strlen(send_data),0,(struct sockaddr *)&client_address, sizeof(struct sockaddr));
fflush(stdout);
}
else printf("\nOOPS! What happened? SERVER");
} //end else
}//end while
close (socket_fd);
return 0;
}
At first I thought it was a trailing newline, but I took care of that possibility already by changing the '/n' to '/0' if it exists. I really don't understand why this is happening!
//CLIENT
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> //host struct
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>//use select() for multiplexing
#include <sys/fcntl.h> // for non-blocking
#define MAX_LENGTH 1024
#define HOST "localhost" //127.0.0.1
void error(char *message)
{
perror(message);
exit(1);
}
int main()
{
fd_set original_socket;
fd_set original_stdin;
fd_set readfds;
fd_set writefds;
struct timeval tv;
int numfd;
int socket_fd,bytes_recieved;
unsigned int address_length;
struct sockaddr_in server_address;
struct hostent *host;
char send_data[MAX_LENGTH],recieve_data[MAX_LENGTH];
host = (struct hostent *) gethostbyname((char *)HOST);//127.0.0.1
if ((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
error("socket()");
}
int flags = fcntl(socket_fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(socket_fd, F_SETFL, flags);
//fcntl(socket_fd, F_SETFL, O_NONBLOCK); //set socket to non-blocking
// clear the set ahead of time
FD_ZERO(&original_socket);
FD_ZERO(&original_stdin);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
// add our descriptors to the set (0 - stands for STDIN)
FD_SET(socket_fd, &original_socket);//instead of 0 put socket_fd
FD_SET(socket_fd, &readfds);
FD_SET(0,&original_stdin);
FD_SET(0, &writefds);
// since we got s2 second, it's the "greater", so we use that for
// the n param in select()
numfd = socket_fd + 1;
// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
tv.tv_sec = 10;
tv.tv_usec = 500000;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(5000);
server_address.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_address.sin_zero),8);
address_length = sizeof(struct sockaddr);
printf("Type (q or Q) at anytime to quit\n");
while (1)
{
readfds = original_socket;
writefds = original_stdin;//problem
int recieve = select(numfd, &readfds, /*NULL*/&writefds, NULL, &tv);
if (recieve == -1)
{
perror("select"); // error occurred in select()
}
else if (recieve == 0)
{
printf("Timeout occurred! No data after 10.5 seconds.\n");
}
else
{
// one or both of the descriptors have data
if (FD_ISSET(socket_fd, &readfds)) //if set to read
{
FD_CLR(socket_fd, &readfds);//clear the set
bytes_recieved = recvfrom(socket_fd,recieve_data, sizeof(recieve_data),0,(struct sockaddr *)&server_address,&address_length);
recieve_data[bytes_recieved]= '\0';
if((strcmp(recieve_data , "q") == 0) || (strcmp(recieve_data , "Q") == 0)) //if client quit, then quit also
{
printf("\nServer has exited the chat.\n");
break;
}
printf("\n(%s , %d) said: %s\n",inet_ntoa(server_address.sin_addr),ntohs(server_address.sin_port),recieve_data);
//inet_ntoa returns an ip address ipv4 style, ex: 127.0.0.1, and ntohs returns the port in the converted byte ordering
}
else if (FD_ISSET(0/*socket_fd*/, &writefds)) //if set to write
//else
{
FD_CLR(0, &writefds);
printf("ClIENT: ");
fgets (send_data, MAX_LENGTH, stdin);
if ((strlen(send_data)>0) && (send_data[strlen (send_data) - 1] == '\n')) //remove trailing newline, if exists
{
send_data[strlen (send_data) - 1] = '\0';
}
if ((strcmp(send_data , "q") == 0) || strcmp(send_data , "Q") == 0) //if user quits, then send an invisible message to server to quit also
{
sendto(socket_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&server_address, sizeof(struct sockaddr));
break;
}
else
{
sendto(socket_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&server_address, sizeof(struct sockaddr));
}
}
else printf("\nOOPS! What happened? CLIENT");
} //end else
} // end while
close (socket_fd);
}
Your mistake is that with select() you wait for the socket to be readable (which is right) and STDIN to be writable (which is wrong, since the terminal is writable most of the time). You have to wait for both socket or STDIN to be readable, i. e. both file descriptors are to be set in readfds, and NULL can be passed instead of &writefds.