Pagefault when using recvfrom() in VxWorks - sockets

I have a weird problem with the posix socket api in vxworks 5.5.1. The code is trivial and probably not interesting (added below), but the gist of it is: When calling socket() and bind() in a separate function from the one calling recvfrom(), a pagefault occurs at the recvfrom() call. If everything is done in the same function it works fine. Note that the fault happens immediately when calling recvfrom(), not when a packet arrives.
Does VxWorks use the stack in some unexpected way for this API?
Edit: Added some code. The te_serve1() function works fine, but te_serve_one() (using helper functions) do not.
#include <taskLib.h>
#include <sysLib.h>
#include <string.h>
#include <taskLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <types.h>
#include <sys/socket.h>
#include <sockLib.h>
#include <netinet/in.h>
#ifdef DEBUG
#define DP(...) printf(__VA_ARGS__)
#else
#define DP(...) do { } while(0)
#endif
#define LLB(l, b) ((l & (0x000000FF << (b*8))) >> b*8)
struct msg_log {
unsigned long src;
int size;
};
static int setup(short port)
{
int err = 0;
struct sockaddr_in addr;
int sock;
DP("socket()\n");
err = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (err < 0)
return err;
sock = err;
addr.sin_family = AF_INET;
addr.sin_port = htons(7357);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
DP("bind()\n");
err = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (err) {
close(sock);
return err;
}
return sock;
}
static int serve(int sock, struct msg_log *log)
{
char buf[32];
struct sockaddr_in caddr;
int caddr_len = sizeof(caddr);
int ret;
int len;
bzero((char *)&caddr, sizeof(caddr));
DP("recvfrom()\n");
ret = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *) &caddr, &caddr_len);
if (ret < 0) return ret;
len = ret;
if (log) {
DP("log()");
log->src = caddr.sin_addr.s_addr;
log->size = len;
}
DP("sendto()");
ret = sendto(sock, (caddr_t) &buf, len, 0, (struct sockaddr *) &caddr, caddr_len);
return ret;
}
static void serve_multiple(int sock)
{
for (;;)
if (serve(sock, NULL) < 0) break;
}
int te_serve_one(void)
{
DP("%s\n", __FUNCTION__);
int sock;
struct msg_log log; /* = {0}; */
int ret = 0;
short port = 1234;
DP("setup()\n");
sock = setup(port);
if (sock < 0)
goto out;
sock = ret;
ret = serve(sock, &log);
if(ret < 0)
goto tidy;
DP("report:\n");
printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n",
log.size,
LLB(log.src, 0),
LLB(log.src, 1),
LLB(log.src, 2),
LLB(log.src, 3));
tidy:
DP("close()");
close(sock);
out:
return ret;
}
int te_serve1(short port)
{
int ret = 0;
int sock;
struct sockaddr_in addr;
char buf[32];
struct sockaddr_in caddr;
int caddr_len = sizeof(caddr);
int len;
DP("socket()\n");
ret = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ret < 0)
goto out;
sock = ret;
/* host addr */
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
DP("bind()\n");
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret)
goto tidy;
/* serve */
for (;;) {
DP("recvfrom()\n");
ret = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *) &caddr, &caddr_len);
if (ret < 0)
break;
len = ret;
if (len >= 4 && !strncmp(buf, "kill", 4)) {
ret = 0;
break;
}
DP("sendto()\n");
ret = sendto(sock, (caddr_t) &buf, len, 0,
(struct sockaddr *) &caddr, caddr_len);
printf("Echo'd %d byte to %lu.%lu.%lu.%lu\n",
len,
LLB(caddr.sin_addr.s_addr, 0), LLB(caddr.sin_addr.s_addr, 1),
LLB(caddr.sin_addr.s_addr, 2), LLB(caddr.sin_addr.s_addr, 3));
}
tidy:
DP("close()");
close(sock);
out:
return ret;
}

settup() declares following local:
struct sockaddr_in addr;
What happens if you declare "struct sockaddr_in addr;" in te_serve_one() and pass it to setup()?

Looking at the optimized assembly, I realized that the sock variable got overwritten by ret, which at that point is unused and initialized to zero. Splendid.

Related

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.

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

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?

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.