libevent sending out POST instead of GET - sockets

I wrote a simple program to make simultaneous connections to a web server using libevent with this sample code
#include <stdio.h>
#include <event2/event.h>
#include <evhttp.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
int success_count = 0;
int failure_count = 0;
time_t start,end;
void _reqhandler(struct evhttp_request *req, void *state)
{
printf("in _reqhandler. state == %s\n", (char *) state);
if (req == NULL) {
printf("timed out!\n");
failure_count ++;
} else if (req->response_code == 0) {
printf("connection refused!\n");
failure_count++;
} else if (req->response_code != 200) {
printf("error: %u %s\n", req->response_code, req->response_code_line);
failure_count++;
} else {
printf("success: %u %s\n", req->response_code, req->response_code_line);
success_count++;
}
evhttp_connection_free((evhttp_connection*)state);
}
void* thread_func(void* arg)
{
printf("starting event loop..\n");
sleep(1);
event_base_dispatch((struct event_base*)arg);
printf("returning");
}
int main(int argc, char *argv[])
{
struct event_base* base = event_init();
printf("Using Libevent with backend method %s.",event_base_get_method(base));
pthread_t id;
int ret = pthread_create(&id,NULL,thread_func,base);
int x = 10;
start = time (NULL);
while(x--){
printf("%s\n","adding");
const char *addr = "74.125.131.103";
unsigned int port = 80;
struct evhttp_connection *conn;
struct evhttp_request *req;
//printf("initializing libevent subsystem..\n");
conn = evhttp_connection_new(addr, port);
evhttp_connection_set_timeout(conn, 5);
req = evhttp_request_new(_reqhandler, (void *)conn);
evhttp_add_header(req->output_headers, "Host", addr);
evhttp_add_header(req->output_headers, "Content-Length", "0");
evhttp_make_request(conn, req, EVHTTP_REQ_GET, "/");
}
pthread_join( id, NULL);
end = time(NULL);
double dif = difftime(end,start);
printf("total seconds taken: %.2lf for %d success connections and %d failed
connections\n", dif, success_count,failure_count);
return 0;
}
I am running this on a vmware fusion with centos on it. The problem is that when i run it I get only connection refused from the servers. On further investigation with wireshark, I realized that this piece of code is making a HTTP POST request instead of GET from behind and hence the conneciton refused. now the same code works well on my mac or ubuntu machines. it seems like a configuration issue with virtual os. Can anyone point out what it could possible be? This is what my virtual os is sending out:
POST / HTTP/1.1
Host: 74.125.131.103
Content-Length: 0
HTTP/1.1 405 Method Not Allowed

Related

Socket programming error, "Socket operation on non-socket"

This question has been asked many times, but searching through and implementing some solutions that have worked for others, I still haven't been able to figure out what I'm doing wrong. I am still having issues understanding programming with sockets, so any explanations would be greatly appreciated. The function where I am getting the error is "int forwardClientReq(char* buffer, char* hostname, int clientfd)" and more specifically around this:
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
if(numBytesSent == -1)
printf("Oh dear, something went wrong with send()! %s\n", strerror(errno));
The full code is as follows:
/* Proxy application called webproxy */
// Copy past http server includes, remove unnecessary
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for fgets */
#include <strings.h> /* for bzero, bcopy */
#include <unistd.h> /* for read, write */
#include <sys/socket.h> /* for socket use */
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
#define MAXBUF 8192 /* max text line length */
#define LISTENQ 1024 /* second argument to listen() */
#define ERRBUFSIZE 1024
#define HEAPBUF 32768 // 2^15
int open_listenfd(int port);
void webProxy(int connfd);
void *thread(void *vargp);
int connect2Client(char* ip, char* port);
void sendErrResponse(char* errBUF, int connfd);
int forwardClientReq(char* buffer, char* host, int clientfd);
int main(int argc, char **argv)
{
int timeout = 0;
/* Check if the function was called correctly */
/* Store arguments provided (port number & cache timeout) */
if(argc < 2 || argc > 3){
fprintf(stderr, "Incorrect arguments, Usage: ./<executableFile> <port#> <timeout(optional)>\n");
exit(0);
}
if(argc == 3)
timeout = atoi(argv[2]);
int listenfd, *connfdp, port, clientlen=sizeof(struct sockaddr_in);
pthread_t tid;
struct sockaddr_in clientaddr;
port = atoi(argv[1]); // store the port number
listenfd = open_listenfd(port); // create persistant TCP socket for client HTTP requests
/* Create,Bind,Listen SOCKET and multithread */
while (1) {
connfdp = malloc(sizeof(int)); // pointer to pass the socket
*connfdp = accept(listenfd, (struct sockaddr*)&clientaddr, &clientlen);
if(*connfdp<0)
printf("There is an error accepting the connection with the client");
pthread_create(&tid, NULL, thread, connfdp); // call thread function with tid
}
}
/* thread routine */
void * thread(void * vargp)
{
int connfd = *((int *)vargp);
pthread_detach(pthread_self());
free(vargp);
webProxy(connfd);
close(connfd);
return NULL;
}
void webProxy(int connfd)
{
size_t n;
char buffer[MAXBUF]; // pointer to pass the socket
char errorBuf[ERRBUFSIZE];
bzero(errorBuf, ERRBUFSIZE);
bzero(buffer, MAXBUF);
char httpmsg[]="HTTP/1.1 200 Document Follows\r\nContent-Type:text/html\r\nContent-Length:32\r\n\r\n<html><h1>Hello CSCI4273 Course!</h1>";
char hostname[50];
n = read(connfd, buffer, MAXBUF); // read the requst up to maxbuf sizeof
printf("server received the following request:\n%s\n",buffer);
/* parse the request */
char requestType[50], fullPath[50];
bzero(requestType, 50);
bzero(fullPath, 50);
sscanf(buffer, "%s %s", requestType, fullPath);
printf("requestType = %s, and fullPath= %s\n", requestType, fullPath);
/* I tried a million different methods and libary suggestions but this is the only
method that I found to easily parse the information I wanted to input */
// sscanf(fullPath, "http://www.%511[^/\n]", hostname);
sscanf(fullPath, "http://%511[^/\n]", hostname);
printf("hostname is = %s\n", hostname);
/* support only GET requests */
if(strcmp(requestType, "GET") != 0)
{
printf("Proxy received a request that was not a 'GET' Request, sending 400 Bad Request response\n");
sendErrResponse(errorBuf, connfd);
}
// // /* support only HTTP/1.1 */
// else if(strcmp(Type, "HTTP/1.1") != 0)
// {
// printf("Proxy received a request that was not an HTTP/1.1 version, sending 400 Bad Request response");
// // I think the error message below is 80, but I could be wrong. Need to double check or use strlen function
// sprintf(errorBuf, "HTTP/1.1 400 Bad Request\r\nContent-Type:text/html\r\nContent-Length: %d\r\n\r\n",80);
// write(connfd, errorBuf, strlen(errorBuf));
// bzero(errorBuf, ERRBUFSIZE);
// }
/* parse and verify the hostname/server */
struct hostent *host = gethostbyname(hostname);
if (host == NULL) {
fprintf(stderr,"ERROR, no such host as %s\n", hostname);
sendErrResponse(errorBuf, connfd);
exit(0);
}
else{
/* Forward request to HTTP server */
forwardClientReq(buffer, hostname, connfd);
printf("buffer = %s\n", buffer);
/* Relay data from server to client */
}
}
int forwardClientReq(char* buffer, char* hostname, int clientfd)
{
char* serverResponse = malloc(HEAPBUF); // create a buffer for receiving the response from the server
bzero(serverResponse, HEAPBUF); // zeroize the buffer
/* open a socket with the server */
struct sockaddr_in serveraddr;
int serverSock, optval =1;
/* Create a socket descriptor */
if(-1 == (serverSock = socket(AF_INET, SOCK_STREAM, 0))) // yoda condition...
{
printf("Error: Unable to create socket in 'open_listenfd' function");
return -1;
}
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(serverSock, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) < 0){
printf("Error in setsockopt in forwardClientReq function");
return -1;
}
struct hostent* host = gethostbyname(hostname);
serveraddr.sin_family = AF_INET;
memcpy(&serveraddr.sin_addr, host->h_addr_list[0], host->h_length);
serveraddr.sin_port = htons(80); //(you should pick the correct remote port or use the default 80 port if noneis specified).
socklen_t addrlen = sizeof(serveraddr); // The addrlen argument specifies the size of serveraddr.
int serverfd = connect(serverSock, (struct sockaddr*) &serveraddr, addrlen);
if(serverfd < 0)
printf("improper connection when trying to forward client's request/n");
/* send the client message to the server */
int numBytesSent = 0;
printf("buffer before send = %s\n", buffer);
sprintf(buffer, "\r\n\r\n");
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
if(numBytesSent == -1)
printf("Oh dear, something went wrong with send()! %s\n", strerror(errno));
// printf("Sent %d to the server", numBytesSent);
// /* store the server's response */
// int numBytesRead = 0;
// numBytesRead = read(serverfd, serverResponse, HEAPBUF);
// printf("Sent %d to the server", numBytesRead);
//
// /* send the response to the client. This is a moment here the proxy can cache the page,
// inspect the data, and do all kinds of cool proxy-level things */
// numBytesSent = write(clientfd, serverResponse, strlen(serverResponse));
// printf("Sent %d to the server", numBytesSent);
free(serverResponse); // free malloc'd space
}
int open_listenfd(int port)
{
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Error: Unable to create socket in 'open_listenfd' function");
return -1;
}
/* Eliminates "Address already in use" error from bind. */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval , sizeof(int)) < 0)
return -1;
/* listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
/* bind: associate the parent socket with a port */
if (bind(listenfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0)
return -1;
return listenfd;
} /* end open_listenfd */
void sendErrResponse(char* errorBuf, int connfd)
{
// I think the error message below is 80, but I could be wrong. Need to double check or use strlen function
sprintf(errorBuf, "HTTP/1.1 400 Bad Request\r\nContent-Type:text/html\r\nContent-Length: %d\r\n\r\n",80);
write(connfd, errorBuf, strlen(errorBuf));
bzero(errorBuf, ERRBUFSIZE);
}
The return value of connect is an error code not a socket fd:
If the connection or binding succeeds, zero is returned. On error,
-1 is returned, and errno is set appropriately.
So
numBytesSent = send(serverfd, buffer, strlen(buffer), 0);
Should be
numBytesSent = send(serverSock, buffer, strlen(buffer), 0);

Unable to receive TCP data on particular IP

I am trying to implement TCP client, server program in C on Linux system. Here are my codes.
Client Source Code :
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
char *address;
// Create socket
int client_socket;
client_socket = socket(AF_INET, SOCK_STREAM, 0);
// Set - Up Server Address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
inet_aton(address, &server_address.sin_addr.s_addr);
// Connect to the server
int connect_stat;
connect_stat = connect(client_socket, (struct sockaddr *) &server_address, sizeof(server_address));
if(connect_stat == -1)
printf("Not Connected\n");
else
printf(" Connected \n");
// Recieve from server
char response[256];
recv(client_socket, &server_address, sizeof(server_address), 0);
// Printing the Response data
printf("Data Recieved : %s\n",response);
// Destroy the socket
close(client_socket);
return 0;
}
Server Source Code :
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
// Address
char *address;
address = argv[1];
// Create message to send
char message[256] = "Connection Established";
// Create server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// Set - Up Server Address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
inet_aton(address, &server_address.sin_addr.s_addr);
// Bind it to an IP and PORT
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
// Start listenting on address
listen(server_socket, 5);
// Start accepting the clients;
int client_socket;
client_socket = accept(server_socket, NULL, NULL);
// Send some data back to client
send(client_socket, message, sizeof(message), 0);
// Close the socket
close(server_socket);
close(client_socket);
return 0;
}
On passing an IP like 192.168.1.xxx to both client and server, server starts waiting for the clients but client always show not connected and thus no data received.
Client output :
root#kali:/home/mayank/Desktop/tcp_chat# ./tcp_client 192.168.1.111
Not Connected
Data Recieved :
But if i use INADDR_ANY instead of specific IP, it works. I know INADDR_ANY basically means it binds to all IP address, but why it is not binding to specific IP address which i want. Any suggestions, where i am wrong.
Instead of inet_aton(), you can also use
server_address.sin_addr.s_addr = inet_addr("IP address");
And use perror() after every function, like
client_socket = socket(...);
if (client_socket == -1)
perror("socket");
You are not doing any error checking, except on the connect() call. For example, you are getting an ENOTSOCK error because you are not checking whether socket() succeeds or fails.
Beyond that, on the client side, this statement:
inet_aton(address, &server_address.sin_addr.s_addr);
Should be this instead:
inet_aton(address, &server_address.sin_addr);
inet_aton() expects a pointer to a struct in_addr, but you are passing it a pointer to a uint32_t instead. In fact, the original code should not have even compiled because of that.
But, more importantly, your address variable is uninitialized, so you are passing a bad memory pointer to inet_aton(), and not checking its return value for failure.
Even if you could connect to the server, you are also passing the wrong output buffer to recv(), so you would end up writing garbage to the console.
Try this instead:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("usage: %s <IPv4 address>\n", argv[0]);
return 0;
}
// Set - Up Server Address
struct sockaddr_in server_address = {0};
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
if (inet_aton(argv[1], &server_address.sin_addr) != 0)
{
printf("invalid IPv4 address specified\n");
return 0;
}
// Create socket
int client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client_socket == -1)
{
perror("socket() failed");
return 0;
}
// Connect to the server
if (connect(client_socket, (struct sockaddr *) &server_address, sizeof(server_address)) == -1)
{
perror("Not Connected");
}
else
{
printf("Connected\n");
// Receive from server
char response[256];
int numRecvd = recv(client_socket, response, sizeof(response), 0);
// Printing the Response data
if (numRecvd == -1)
perror("recv() failed");
else if (numRecvd == 0)
printf("Disconnected by server\n");
else
printf("Data Received: [%d] %.*s\n", numRecvd, numRecvd, response);
}
// Destroy the socket
close(client_socket);
return 0;
}
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
// Set - Up Server Address
struct sockaddr_in server_address = {0};
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8001);
if (argc >= 2)
{
if (inet_aton(argv[1], &server_address.sin_addr) != 0)
{
printf("invalid IPv4 address specified\n");
return 0;
}
}
else
server_address.sin_addr.s_addr = INADDR_ANY;
// Create message to send
char message[256] = "Connection Established";
// Create server socket
int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == -1)
{
perror("socket() failed");
return 0;
}
// Bind it to an IP and PORT
if (bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address)) == -1)
{
perror("bind() failed");
}
// Start listenting on address
else if (listen(server_socket, 5) == -1)
{
perror("listen() failed");
}
// Start accepting the clients
else
{
int client_socket = accept(server_socket, NULL, 0);
if (client_socket == -1)
{
perror("accept() failed");
}
else
{
// Send some data back to client
int numSent = send(client_socket, message, sizeof(message), 0);
if (numSent == -1)
perror("send() failed");
else
printf("Data Sent: [%d] %.*s\n", numSent, numSent, message);
// Close the socket
close(client_socket);
}
}
// Destroy the socket
close(server_socket);
return 0;
}

How can I know the service name?

This code from Stevens et al., Advanced Programming in the Unix Environment, Figure 16.17 is a server program to provide system uptime:
#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <syslog.h>
#include <sys/socket.h>
#define BUFLEN 128
#define QLEN 10
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 256
#endif
extern int initserver(int, const struct sockaddr *, socklen_t, int);
void
serve(int socked);
int
main(int argc, char *argv[])
{
struct addrinfo *ailist, *aip;
struct addrinfo hint;
int sockfd, err, n;
char *host;
if (argc != 1)
err_quit("usage: ruptimed");
if ((n = sysconf(_SC_HOST_NAME_MAX)) < 0)
n = HOST_NAME_MAX; /* best guess */
if ((host = malloc(n)) == NULL)
err_sys("malloc error");
if (gethostname(host, n) < 0)
err_sys("gethostname error");
daemonize("ruptimed");
memset(&hint, 0, sizeof(hint));
hint.ai_flags = AI_CANONNAME;
hint.ai_socktype = SOCK_STREAM;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;
if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s",
gai_strerror(err));
exit(1);
}
for (aip = ailist; aip != NULL; aip = aip->ai_next) {
if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr,
aip->ai_addrlen, QLEN)) >= 0) {
serve(sockfd);
exit(0);
}
}
exit(1);
}
What confused me is the function call getaddrinfo, it just tells me the service name is ruptime, and I have no idea where this name comes from. Did the service-name get named after the name of this program? How can I determine the service name? Can I designate the service name by myself?
I didn't duplicate the code of initserver and serve, because I think it doesn't concern the question.
The service name is simply a key to look up in /etc/services; i.e. it's a symbolic reference to a port number.

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?

Fail to connect two sockets which are bound with two public IP address in a server

I tried to setup a XSTUNT server on Linux(http://www.cis.nctu.edu.tw/~gis87577/xDreaming/XSTUNT/index.html) to do p2p traversal, but failed. I read the source code of it. I found the application creates two TCP sockets and then bind them to the two public IP addresses respectively. The remote client is able to connect only one of the public IP address.
So I wrote a simple server application to test this environment.
On the remote client, I use this two commands
"nc [public IP_A] [PORT]" and
"nc [public IP_B] [PORT]"
to try to connect to the server. Only one is successful, while the other fail. I have sniffer the traffic on the client, the nc which is failed can not get "SYN-ACK" package from the server. Is it the route problem? My two public interfaces do NOT have special gateway. Because I use PPPoE to connect to the Internet. So I just get ppp0 and ppp1. I don't know how to change the route table if the route table cause this problem.
However, If I do these two command on the server which is running my sever application, both commands are successful. Who can tell me why?
NOTE: I compiled this server application on Windows with cygwin. The result is the same.
Here is the code of my server application
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SERVPORT 3333 /* Listen Port */
#define BACKLOG 10
int main(int argc, char **argv)
{
int sockfd[2],client_fd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr; /* client socket info */
int sin_size;
int maxfd;
fd_set rfds;
int i;
if(argc != 3)
{
printf("Usage: %s <IP_1> <IP_2>\n", argv[0]);
return 1;
}
for(i = 0; i < 2; i++)
{
if ((sockfd[i] = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket error!"); exit(1);
}
else
{
printf("Create sockfd[%d] = %d\n", i, sockfd[i]);
}
}
// set the first Socket
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = inet_addr(argv[1]);
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd[0], (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind error!");
exit(1);
}
// set the second Socket
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = inet_addr(argv[2]);
bzero(&(my_addr.sin_zero),8);
if (bind(sockfd[1], (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind error!");
exit(1);
}
for(i = 0; i < 2; i++)
{
if (listen(sockfd[i], BACKLOG) == -1) {
perror("listen error!");
exit(1);
}
}
if(sockfd[0] > sockfd[1])
maxfd = sockfd[0];
else
maxfd = sockfd[1];
while(1) {
FD_ZERO(&rfds);
FD_SET(sockfd[0], &rfds);
FD_SET(sockfd[1], &rfds);
printf("waiting client\n");
select(maxfd + 1, &rfds, NULL, NULL, NULL);
sin_size = sizeof(struct sockaddr_in);
if(FD_ISSET(sockfd[0], &rfds))
{
printf("sockfd[0](%s) is readable\n", argv[1]);
if ((client_fd = accept(sockfd[0], (struct sockaddr *)&remote_addr, (socklen_t *)&sin_size)) == -1) {
perror("accept error");
continue;
}
}
else if(FD_ISSET(sockfd[1], &rfds))
{
printf("sockfd[1](%s) is readable\n", argv[2]);
if ((client_fd = accept(sockfd[1], (struct sockaddr *)&remote_addr, (socklen_t *)&sin_size)) == -1) {
perror("accept error");
continue;
}
}
else
{
printf("select error\n");
continue;
}
printf("received a connection from %s:%d\n\n", (char *)inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port));
if (!fork()) { /* child process */
if (send(client_fd, "Hello, you are connected!\n", 26, 0) == -1)
perror("send error!");
close(client_fd);
exit(0);
}
close(client_fd);
}
}