Why is the client's file descriptor used while calling the recv and send funtions on both server and client sides? - sockets

TCPServer
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/ip.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd == -1)
{
printf("socket failed!\n");
exit(0);
}
printf("Enter port: ");
int port;
scanf("%d",&port);
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
int bind_ret = bind(fd, (struct sockaddr*)(&server), sizeof(server));
if(bind_ret == -1)
{
printf("bind failed!\n");
exit(0);
}
int listen_ret = listen(fd, 10);
if(listen_ret == -1)
{
printf("listen failed!\n");
exit(0);
}
struct sockaddr_in client;
int l = sizeof(client);
int client_fd = accept(fd, (struct sockaddr*)(&client), &l);
if(client_fd == -1)
{
printf("accept failed!\n");
exit(0);
}
while(1)
{
char msg_recv[50];
int recv_ret = recv(client_fd, msg_recv, sizeof(msg_recv),0);
if(recv_ret == -1)
{
printf("recv failed!\n");
exit(0);
}
msg_recv[recv_ret]='\0';
if(strcmp("bye",msg_recv)==0)
{
exit(0);
}
printf("Message recieved: %s\n",msg_recv);
char msg_send[50];
printf("Enter message: ");
scanf(" %s",msg_send);
int send_ret = send(client_fd, msg_send, strlen(msg_send),0);
if(send_ret == 0)
{
printf("send failed!\n");
}
if(strcmp("bye",msg_send) == 0)
exit(0);
}
}
TCPClient
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/ip.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
int main()
{ int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd == -1)
{
printf("socket failed!\n");
exit(0);
}
int port;
printf("Enter port number: ");
scanf("%d",&port);
struct sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(port);
client.sin_addr.s_addr = INADDR_ANY;
int connect_ret = connect(fd, (struct sockaddr*)(&client), sizeof(client));
if(connect_ret == -1)
{
printf("connect failed!\n");
exit(0);
}
while(1)
{
printf("Enter message: ");
char msg_send[50];
scanf("%s",msg_send);
int send_ret = send(fd, msg_send, strlen(msg_send), 0);
if(send_ret == -1)
{
printf("send failed!\n");
exit(0);
}
if(strcmp("bye", msg_send)==0)
{
exit(0);
}
char msg_recv[50];
int recv_ret = recv(fd, msg_recv, sizeof(msg_recv), 0);
if(recv_ret == -1)
{
printf("recv failed!\n");
exit(0);
}
msg_recv[recv_ret]= '\0';
if(strcmp("bye", msg_recv) == 0)
exit(0);
printf("Message recieved: %s \n",msg_recv);
}
}
In the above program for Server, recv and send were called by passing client_fd as the argument, while in the program for Client, recv and send were called by passing fd as the argument. I wanted to know why on the server side we did not use its own socket file descriptor like we did on the client side?

The server’s fd descriptor is a listen()’ing socket. It can’t perform any I/O, only receive incoming client connections. accept() pulls a pending client connection from fd’s queue and returns a new socket descriptor that can perform I/O with that client.
The client’s fd descriptor is a connect()‘ing socket. It can perform I/O with the server once its connection has been accepted.

Related

Unable to connect to local server in VPN

I have tried below code in multiple iOS, MacOS.
This is server code
void *run_server(void *thread_id) {
int server_fd, new_socket;
struct sockaddr_in server, client;
int opt = 1;
int addrlen = sizeof(server);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket");
return NULL;
}
// Forcefully attaching socket to the port
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
perror("setsockopt");
return NULL;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = ip("10.10.10.20"); // bind IP
server.sin_port = htons(27042);
// Forcefully attaching socket to the port
if (bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind");
return NULL;
}
if (listen(server_fd, 3) < 0) {
perror("listen");
return NULL;
}
printf("Server is running with %u:%d\n", server.sin_addr.s_addr, htons(server.sin_port));
while (1) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&client, (socklen_t*)&addrlen))<0) {
perror("accept");
return NULL;
}
printf("Client connected with %u:%d\n", client.sin_addr.s_addr, client.sin_port);
}
}
This is client code
void scan(unsigned int ip, int port) {
int sock = 0;
struct sockaddr_in serv_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\nSocket creation error\n");
return;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = ip;
printf("IP %u, port %d\n", ip, port);
int connected = connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (connected != 0) {
char errorMsg[256];
strerror_r(errno, errorMsg, 256);
printf("Error %s\n", errorMsg);
}
if (connected < 0) {
close(sock);
return;
}
}
void *run_scan(void *thread_id) {
while (1) {
scan(ip("10.10.10.20"), 27042);
usleep(1000000);
}
return NULL;
}
And the main function
int main(int argc, const char * argv[]) {
pthread_t thread1;
if (pthread_create(&thread1, NULL, run_server, (void *)1)) {
printf("Can't create thread run_server");
}
pthread_t thread2;
if (pthread_create(&thread2, NULL, run_scan, (void *)2)) {
printf("Can't create thread run_scan");
}
while (1) sleep(1);
return 0;
}
Problem description:
This code is working normally with local IP (DHCP assigned IP). However when I connect to VPN and bind server IP to PPP network interface IP which is 10.10.10.20 (as above example code). I could not be able to open connect to that IP. The error is "Connection timeout". Note, the other host can still be able to connect to the server with IP 10.10.10.20.
Appreciate if any knowledge sharing regarding this situation.
Found the answer, basically this is a restriction imposed by the Linux kernel.
More info: https://www.softether.org/4-docs/1-manual/B._Troubleshooting_and_Supplemental/11.1_Troubleshooting

send failed with error 10093 and shutdown failed with error 10093

class socketClient
{
private:
SOCKET ConnectSocket;
int numBlock;
public:
socketClient()
{
WSADATA wsaData;
numBlock = countObj;
++countObj;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
ssPrintf("WSAStartup failed: %d\n", iResult);
//return 1;
}
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
ssPrintf("Error at socket(): %ld\n", WSAGetLastError());
//freeaddrinfo(result);
WSACleanup();
//return 1;
}
}
void sConnect(char* myHost, int myPort)
{
int iResult;
char port[5];
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort,port,5,10);
iResult = getaddrinfo(myHost, porgt, &hints, &result);
if ( iResult != 0 )
{
ssPrintf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
//return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
}
~socketClient()
{
int iResult;
--countObj;
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
//return 1;
}
closesocket(ConnectSocket);
WSACleanup();
}
int getNumBlock()
{
return numBlock;
}
int sWrite(std::string str)
{
int iResult;
// Send an string
iResult = send( ConnectSocket, str.c_str(), str.size(), 256 );
if (iResult == SOCKET_ERROR)
{
ssPrintf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
//return 1;
}
return iResult; //pocet odeslanych bytu
}
};
I am trying to send string to the client model but while running the model, I am getting error as:
send failed 10093 and
shutdown failed 10093.
Please do let me know what can I change in this code.
Socket error 10093 (WSANOTINITIALIZED) means either:
WSAStartup() has not been called, or it failed
WSACleanup() has been called too many times.
In this case, your code is calling WSACleanup() in places it does not belong:
sConnect() calls WSACleanup() if getaddrinfo() fails
sWrite() calls WSACleanup() if send() fails.
~socketClient() calls WSACleanup() an extra time if shutdown() fails.
WSAStartup() and WSACleanup() must be balanced. For each successful call to WSAStartup(), you must call WSACleanup() once and only once. In this case, only your destructor should be calling WSACleanup(), and only if WSAStartup() was successful in the constructor.
Your code also has other errors in it as well.
Try something more like this instead:
class socketClient
{
private:
SOCKET ConnectSocket;
int numBlock;
bool WSAInitialized;
// private to prevent copies
socketClient(const socketClient&)
: ConnectSocket(INVALID_SOCKET), WSAInitialized(false)
{
numBlock = countObj++;
}
socketClient& operator=(const socketClient&)
{
return *this;
}
public:
socketClient()
: ConnectSocket(INVALID_SOCKET), WSAInitialized(false)
{
numBlock = countObj++;
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
ssPrintf("WSAStartup() failed: %d\n", iResult);
return;
}
WSAInitialized = true;
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
ssPrintf("socket() failed: %d\n", WSAGetLastError());
return;
}
}
~socketClient()
{
--countObj;
if (ConnectSocket != INVALID_SOCKET)
{
shutdown(ConnectSocket, SD_SEND);
closesocket(ConnectSocket);
}
if (WSAInitialized)
WSACleanup();
}
bool sConnect(char* myHost, int myPort)
{
char port[6];
struct addrinfo *result = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort, port, 6, 10);
int iResult = getaddrinfo(myHost, port, &hints, &result);
if (iResult != 0)
{
ssPrintf("getaddrinfo() failed: %d\n", iResult);
return false;
}
// Connect to server.
if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
{
ssPrintf("connect() failed: %d\n", WSAGetLastError());
freeaddrinfo(result);
return false;
}
freeaddrinfo(result);
return true;
}
int getNumBlock()
{
return numBlock;
}
bool sWrite(const std::string &str)
{
int iResult;
const char *ptr = str.c_str();
int len = str.size();
// Send an string
while (len > 0)
{
iResult = send( ConnectSocket, ptr, len, 0 );
if (iResult == SOCKET_ERROR)
{
ssPrintf("send() failed: %d\n", WSAGetLastError());
return false;
}
ptr += iResult;
len -= iResult;
}
return true;
}
};
Since you are coding in C++, you should consider using exceptions and RAII techniques instead, eg:
#include <stdexcept>
#include <memory>
class winsock_error : public std::runtime_error
{
public:
int errorCode;
winsock_error(const std::string &msg, int error)
: std::runtime_error(msg), errorCode(error)
{
}
};
class wsaInit
{
private:
void init()
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
throw winsock_error("WSAStartup() failed", iResult);
}
public:
wsaInit()
{
init();
}
wsaInit(const wsaInit &)
{
init();
}
~wsaInit()
{
WSACleanup();
}
};
struct socketDeleter
{
typedef SOCKET pointer;
void operator()(SOCKET s)
{
if (s != INVALID_SOCKET)
{
shutdown(s, SD_BOTH);
closesocket(s);
}
}
};
typedef std::unique_ptr<SOCKET, socketDeleter> socket_ptr;
typedef std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> addrinfo_ptr;
class socketClient
{
private:
wsaInit wsa;
socket_ptr ConnectSocket;
int numBlock;
public:
socketClient()
: ConnectSocket(INVALID_SOCKET)
{
numBlock = countObj++;
}
socketClient(const socketClient&) = delete;
socketClient& operator=(const socketClient&) = delete;
~socketClient()
{
--countObj;
}
void sConnect(char* myHost, int myPort)
{
char port[6];
struct addrinfo *result = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort, port, 6, 10);
int iResult = getaddrinfo(myHost, port, &hints, &result);
if (iResult != 0)
throw winsock_error("getaddrinfo() failed", iResult);
addrinfo_ptr result_ptr(result, &::freeaddrinfo);
// Connect to server.
int errorCode = 0;
for(struct addrinfo *ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
// Create a SOCKET for connecting to server
socket_ptr sock( socket(result->ai_family, result->ai_socktype, result->ai_protocol) );
if (sock.get() == INVALID_SOCKET)
throw winsock_error("socket() failed", WSAGetLastError());
if (connect(sock.get(), result->ai_addr, (int)result->ai_addrlen) != SOCKET_ERROR)
{
ConnectSocket = std::move(sock);
return;
}
errorCode = WSAGetLastError();
}
throw winsock_error("connect() failed", errorCode);
}
int getNumBlock()
{
return numBlock;
}
void sWrite(const std::string &str)
{
int iResult;
const char *ptr = str.c_str();
int len = str.size();
// Send an string
while (len > 0)
{
iResult = send(ConnectSocket.get(), ptr, len, 0);
if (iResult == SOCKET_ERROR)
throw winsock_error("send() failed", WSAGetLastError());
ptr += iResult;
len -= iResult;
}
}
};

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?

Why does bind return the same ephemeral port?

I have a problem where I create two UDP sockets, bind them to the loopback address with port 0 (requesting the stack to assign an ephemeral port). My understanding is that both sockets should be on different ports. In the code example below, both sockets are reported to be on the same IP address and port.
#include <stdio.h>
#include <arpa/inet.h>
int main(int, char**)
{
int fd1 = ::socket(AF_INET, SOCK_DGRAM, 0);
if (fd1 < 0)
{
perror("fd1 socket()");
return -1;
}
int fd2 = ::socket(AF_INET, SOCK_DGRAM, 0);
if (fd2 < 0)
{
perror("fd2 socket()");
return -1;
}
// Set SO_REUSEADDR for both sockets
int reuse = 1;
if (::setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("fd1 SO_REUSEADDR failed");
return -1;
}
if (::setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("fd2 SO_REUSEADDR failed");
return -1;
}
sockaddr_storage storage;
socklen_t addrlen = sizeof(storage);
sockaddr_in& addr = reinterpret_cast<sockaddr_in&>(storage);
addr.sin_family = AF_INET;
addr.sin_port = 1234;
addr.sin_port = 0;
if (::inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0)
{
perror("Failed to create address 127.0.0.1");
return -1;
}
sockaddr* pAddr = reinterpret_cast<sockaddr*>(&storage);
if (::bind(fd1, pAddr, addrlen) < 0)
{
perror("bind fd1 failed");
return -1;
}
// Get the local address for fd1
addrlen = sizeof(storage);
if (::getsockname(fd1, pAddr, &addrlen))
{
perror("getsockname for fd1 failed");
return -1;
}
char straddr[INET_ADDRSTRLEN];
if (!inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr)))
{
perror("inet_ntop for fd1 failed");
return -1;
}
printf("fd1=%d addr=%s:%d\n", fd1, straddr, addr.sin_port);
if (::bind(fd2, pAddr, addrlen) < 0)
{
perror("bind fd2 failed");
return -1;
}
// Get the local address for fd2
addrlen = sizeof(storage);
if (::getsockname(fd2, pAddr, &addrlen))
{
perror("getsockname for fd2 failed");
return -1;
}
if (!inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr)))
{
perror("inet_ntop for fd2 failed");
return -1;
}
printf("fd2=%d addr=%s:%d\n", fd2, straddr, addr.sin_port);
return 0;
}
This code gives the following output ...
fd1=4 addr=127.0.0.1:1933
fd2=5 addr=127.0.0.1:1933
I need both sockets on the same (local) IP address, but different ports. Can anyone explain why both sockets share the same port? Can anyone suggest a fix?
That is the expected behavior for SO_REUSEADDR on a UDP socket. Remove that setting to return to normal allocation rules.

Reciving UDP packets on iPhone

I'm trying to establish UDP communication between a MAC OS and an iPod through Wi-Fi, at this point I'm able to send packets from the iPod and I can see those packets have the right MAC and ip addresses (I'm using wireshark to monitor the network) but the MAC receives the packets only when the wireshark is on, otherwise recvfrom() returns -1.
When I try to transmit from MAC to iPhone I have the same result, I can see the packets are sent but the iPhone doesn't seem to get them.
I'm using the next code to send:
struct addrinfo hints;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(IP, SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to bind socket\n");
return 2;
}
while (cond)
sntBytes += sendto(sockfd, message, strlen(message), 0, p->ai_addr, p->ai_addrlen);
return 0;
and this code to receive:
struct addrinfo hints, *p;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // set
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use to AF_INET to force IPv4 my IP
if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
perror("listener: socket");
continue;
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("listener: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "listener: failed to bind socket\n");
return 2;
}
addr_len = sizeof their_addr;
fcntl(sockfd, F_SETFL,O_NONBLOCK);
int rcvbuf_size = 128 * 1024; // That's 128Kb of buffer space.
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
&rcvbuf_size, sizeof(rcvbuf_size));
printf("listener: waiting to recvfrom...\n");
while (cond)
rcvBytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len);
return 0;
What am I missing?
It would be good to get some more information about the length of data you are sending.
I will assume you are trying to send an ASCII string.
Also, this appears to be either never called or an infinite send loop:
while (cond)
sntBytes += sendto(sockfd, message, strlen(message), 0, p->ai_addr, p->ai_addrlen);
You might want to use code that actually includes some error checking:
Send String
int sendResult = send( connectedSocket, stringBuffer, stringLength, 0 );
if (sendResult == -1) {
perror("Error while trying to send string!");
}
else {
NSLog(#"String '%s' sent successfully", stringBuffer );
}
Receive String
memset( ReceiveBuffer, '\0', sizeof(ReceiveBuffer) );
int receiveResult = recv( connectedSocket, ReceiveBuffer, sizeof(ReceiveBuffer), 0);
if ( receiveResult == -1 ) {
perror("recv");
}
else {
NSLog(#"String received successfully: '%s'", ReceiveBuffer );
}