I am using C++ code snippet for port forwarding. The requirement is to do the hand shake between two ports. It should be two way communication. That is to forward what ever iscoming on the source port to destination port. And then to forward the response of the destination port to the source port.
This piece of code is working as expected on my mac system. But when I am running this code on Linux system I am facing one issue.
Issue:
The C++ code that I am using is having 3 parts:
establish_connection_to_source();
open_connection_to_destination();
processconnetion();
On Linux: establish_connection_to_source(); and open_connection_to_destination(); is working perfectly fine. But processconnetion(); is havng one issue.
Following is the process connection method:
void processconnetion()
{
buffer *todest = new buffer(socket_list[e_source].fd,socket_list[e_dest].fd);
buffer *tosrc = new buffer(socket_list[e_dest].fd,socket_list[e_source].fd);
if (todest == NULL || tosrc == NULL){
fprintf(stderr,"out of mememory\n");
exit(-1);
}
unsigned int loopcnt;
profilecommuncation srcprofile(COMM_BUFSIZE);
profilecommuncation destprofile(COMM_BUFSIZE);
while (true) {
int withevent = poll(socket_list, 2, -1);
loopcnt++;
fprintf(stderr,"loopcnt %d socketswith events = %d source:0x%x dest:0x%x\n", loopcnt, withevent, socket_list[e_source].revents, socket_list[e_dest].revents);
if ((socket_list[e_source].revents | socket_list[e_dest].revents) & (POLLHUP | POLLERR)) {
// one of the connections has a problem or has Hungup
fprintf(stderr,"socket_list[e_source].revents= 0x%X\n", socket_list[e_source].revents);
fprintf(stderr,"socket_list[e_dest].revents= 0x%X\n", socket_list[e_dest].revents);
fprintf(stderr,"POLLHUP= 0x%X\n", POLLHUP);
fprintf(stderr,"POLLERR= 0x%X\n", POLLERR);
int result;
socklen_t result_len = sizeof(result);
getsockopt(socket_list[e_dest].fd, SOL_SOCKET, SO_ERROR, &result, &result_len);
fprintf(stderr, "result = %d\n", result);
fprintf(stderr,"exiting as one connection had an issue\n");
break;
}
if (socket_list[e_source].revents & POLLIN) {
srcprofile.increment_size(todest->copydata());
}
if (socket_list[e_dest].revents & POLLIN) {
destprofile.increment_size(tosrc->copydata());
}
}
delete todest;
delete tosrc;
close(socket_list[e_source].fd);
close(socket_list[e_dest].fd);
srcprofile.dumpseensizes("source");
destprofile.dumpseensizes("destination");
}
Here it is giving error - exiting as one connection had an issue that means that if ((socket_list[e_source].revents | socket_list[e_dest].revents) & (POLLHUP | POLLERR)) is returning true. The issue is with the destination port and not in case of source.
Note:
Variales used in the processconnetion(); method:
socket_list is a structure of type pollfd. Following is the description:
struct pollfd {
int fd;
short events;
short revents;
};
pollfd socket_list[3];
#define e_source 0
#define e_dest 1
#define e_listen 2
Following is the output at the time for exit:
connecting to destination: destination IP / 32001.
connected...
loopcnt 1 socketswith events = 1 source:0x0 dest:0x10
socket_list[e_source].revents= 0x0
socket_list[e_dest].revents= 0x10
POLLHUP= 0x10
POLLERR= 0x8
result = 0
exiting as one connection had an issue
int withevent = poll(socket_list, 2, -1); here the withevent value returned is 1
Socket List Initialisation:
guard( (socket_list[e_listen].fd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )), "Failed to create socket listen, error: %s\n", "created listen socket");
void guard(int n, char *msg, char *success)
{
if (n < 0) {
fprintf(stderr, msg, strerror(errno) );
exit(-1);
}
fprintf(stderr,"n = %d %s\n",n, success);
}
I am not able to figure out the issue as it is working fine in mac. Any leads why this behaviour in Linux is highly appreciated. Thanks in advance.
Related
I have tried to set up a server with a specific IP address and Port number by freeDiameter libraries. In other side, there is a client that sends a string message via freeDiameter libraries successfully; I checked it out in Wireshark.
So, here is the problem; when I start listening from the server side, it has no problem until a client sends a connection request; if you look at the below code, "fd_cnx_serv_accept(listener)" is listening to a socket named "listener" which is bind to a specific IP address and Port number.
uint8_t * rcv_buf;
size_t rcv_size;
struct cnxctx * listener_side = NULL;
int ret;
listener_side = fd_cnx_serv_accept(listener);
ret = fd_cnx_start_clear(listener_side, 0);
if(ret != 0){
std::cout<<side<<" is unable to accept connections."<<std::endl;
return -1;
}
ret = fd_cnx_receive(listener_side, NULL, &rcv_buf, &rcv_size);
if(ret == 0){
std::cout<<"Message received."<<std::endl;
listener_side = NULL;
free(rcv_buf);
}
The program works fine until it gets a client request; when "fd_cnx_serv_accept" accept the client side, the program tries to receive the message by "fd_cnx_receive"; but the program stops and shows the error "Segmentation fault (core dumped)". Then, I test the program by gdb and it shows that it is something wrong with the line 309 of "hook.c". Here is the image of the error which is shown by gdb.
Error Screenshot
transcript
multi-thre Thread 0x7fffff72a77 In: fd_hook_call
[New Thread 0x7fffff72a7700 (LWP 1612914)
Thread 2 "server" received signal SIGSEGEV, Segmentation Fault
[Switching to Thread 0x7fffff72a7700 (LWP 1612914)
--Type <RET> for more, q to quit, c to continue without paging --c
0x00007ffff7f2cefc in fd_hook_call (type=HOOD_DATA_RECEIVED, msg=0x0, peer=0x0, other=0x7ffff72a6be0, pmdl=0x7ffff0000ba8 at /root/projects/start_cnx_free/third-party/libfdcore/hooks.c:309
It is good to mention that I am trying to write a c++ program.
How can I solve this problem ?
I solved this problem myself. I forgot to use fd_hooks_init() at the begining of my program to initialize necessary libraries and objects.
Here is the modified code:
/* Initialize the library -- must come first since it initializes the debug facility */
int ret = fd_libproto_init();
if (ret != 0) {
fprintf(stderr, "Unable to initialize libfdproto: %s\n", strerror(ret));
return ret;
}
ret = fd_hooks_init();
if(ret != 0){
std::cout<<"Unable to initialize the hooks."<<std::endl;
return ret;
}
/* Initialize the config with default values */
memset(&g_conf, 0, sizeof(struct fd_config));
fd_g_config = &g_conf;
ret = fd_conf_init();
if (ret != 0) {
printf("Unable to initialize the config with default values.");
return ret;
}
/* Add definitions of the base protocol */
ret = fd_dict_base_protocol(fd_g_config->cnf_dict);
if (ret != 0) {
printf("Unable to add definitions of the base protocol.");
return ret;
}
This issue have bothered me for weeks and I could not find any solution on the web. So I have to create a new question to you gurus.
I was trying to read/write on massive number of sockets, please see test code below. It behave normally when the sockets number is below 1500. When the number of sockets is beyond 1500, the program will crash unexpectedly. I know that I should use command ulimit -n 32768 to increase the open files number limit. But the program still can not behave correctly.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <netdb.h>
#include <errno.h>
#include <malloc.h>
#include <string.h>
int main(int argc, char* argv[])
{
if (argc!=2)
{
printf("usage: test <number of sockets>\n");
return -1;
}
int socketsNum=atoi(argv[1]);
if (socketsNum<=0)
{
printf("error: invalid sockets number\n");
return -1;
}
int *socketHandles=(int*)malloc(sizeof(int)*socketsNum);
if (socketHandles==NULL)
{
printf("error: failed to alloc socket handle memory\n");
return -1;
}
for (int i=0;i<socketsNum;i++)
{
socketHandles[i]=-1;
}
printf("creating %d sockets ...\n",socketsNum);
int createdSocketsNum=0;
for (int i=0;i<socketsNum;i++)
{
int socketHandle=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (socketHandle==-1)
{
int lastError=errno;
printf("warning: socket() failed: index: %d, error: %d\n",i+1,lastError);
continue;
}
sockaddr_in sockAddr; // 0.0.0.0:0
memset(&sockAddr,0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockAddr.sin_port = htons(0);
if (bind( socketHandle, (sockaddr*) &sockAddr, sizeof(sockAddr)) == -1)
{
int lastError=errno;
printf("warning: bind() failed: index: %d, error: %d\n",i+1,lastError);
close(socketHandle);
continue;
}
socketHandles[i]=socketHandle;
createdSocketsNum++;
}
printf("created %d sockets.\n",createdSocketsNum);
//test reading;
printf("testing reading ...\n");
int readableNumber=0;
int unreadableNumber=0;
int readingSkippedNumber=0;
for (int i=0;i<socketsNum;i++)
{
int socketHandle=socketHandles[i];
if (socketHandle==-1)
{
readingSkippedNumber++;
continue;
}
fd_set rset;
FD_ZERO(&rset);
FD_SET(socketHandle, &rset);
struct timeval timeout = {0, 0};
int retCode=select(socketHandle + 1, &rset, NULL, NULL, &timeout);
if (retCode==-1)
{
int lastError=errno;
printf("warning: select() failed: index: %d, error: %d\n",i+1,lastError);
}
else if (retCode==0)
{
unreadableNumber++;
}
else
{
readableNumber++;
}
}
printf("readable: %d, unreadable: %d, skipped: %d, total: %d\n",readableNumber,unreadableNumber,readingSkippedNumber,socketsNum);
//test writing
printf("testing writing ...\n");
int writableNumber=0;
int unwritableNumber=0;
int writingSkippedNumber=0;
for (int i=0;i<socketsNum;i++)
{
int socketHandle=socketHandles[i];
if (socketHandle==-1)
{
writingSkippedNumber++;
continue;
}
fd_set wset;
FD_ZERO(&wset);
FD_SET(socketHandle, &wset);
struct timeval timeout = {0, 0};
int retCode=select(socketHandle + 1, NULL, &wset, NULL, &timeout);
if (retCode==-1)
{
int lastError=errno;
printf("warning: select() failed: index: %d, error: %d\n",i+1,lastError);
}
else if (retCode==0)
{
unwritableNumber++;
}
else
{
writableNumber++;
}
}
printf("writable: %d, unwritable: %d, skipped: %d, total: %d\n",writableNumber,unwritableNumber,writingSkippedNumber,socketsNum);
printf("closing ...\n");
for (int i=0;i<socketsNum;i++)
{
int socketHandle=socketHandles[i];
if (socketHandle==-1)
{
continue;
}
close(socketHandle);
}
free(socketHandles);
printf("completed!\n");
return 0;
}
Compile:
g++ TestSockets.cpp -ldl -g -ggdb -o TestSockets
Config:
ulimit -n 32768
Some typical results:
Good result of ./TestSockets 1500:
creating 1500 sockets ...
created 1500 sockets.
testing reading ...
readable: 0, unreadable: 1500, skipped: 0, total: 1500
testing writing ...
writable: 1372, unwritable: 128, skipped: 0, total: 1500
closing ...
completed!
Bad result of ./TestSockets 1900:
creating 1900 sockets ...
created 1900 sockets.
testing reading ...
warning: select() failed: index: 1797, error: 9
...(more lines trimmed)
warning: select() failed: index: 1820, error: 9
warning: select() failed: index: 1821, error: 22
readable: 0, unreadable: 1878, skipped: 0, total: 1900
testing writing ...
warning: select() failed: index: 1641, error: 9
...(more lines trimmed)
warning: select() failed: index: 1660, error: 9
warning: select() failed: index: 1661, error: 22
writable: 1751, unwritable: 128, skipped: 0, total: 1900
closing ...
completed!
Comment: because 1900>1751+128, it seems that the stack was damaged.
Bad result of ./TestSockets 2000:
creating 2000 sockets ...
created 2000 sockets.
testing reading ...
Segmentation fault
More Investigation:
According to gdb information. It seems that the stack memory was damaged during running:
creating 2000 sockets ...
created 2000 sockets.
testing reading ...
Program received signal SIGSEGV, Segmentation fault.
0x08048b79 in main (argc=2, argv=0xffffd3b4) at TestSockets.cpp:78
78 int socketHandle=socketHandles[i];
(gdb) print socketHandles
$1 = (int *) 0x0
(gdb) info local
socketHandle = 0
rset = {fds_bits = {0 <repeats 32 times>}}
timeout = {tv_sec = 0, tv_usec = 0}
retCode = 0
i = 1601
socketsNum = 2000
unreadableNumber = 1601
unwritableNumber = 134514249
socketHandles = 0x0
createdSocketsNum = 2000
readableNumber = 0
readingSkippedNumber = 0
writableNumber = -136436764
writingSkippedNumber = 0
(gdb) info stack
#0 0x08048b79 in main (argc=2, argv=0xffffd3b4) at TestSockets.cpp:78
An fd_set is limited by the maximum value of the file descriptor (not the number of file descriptors set at the same time). Usually it's 1024.
Thus, if your socket value is greater than 1023, you cannot use select on it at all.
Redefining FD_SETSIZE is not supported on operating systems I know. You might be able to successfully redefine fd_set in your program, but select will only work up to FD_SETSIZE.
I have solved this headache problem. The fd_set on windows and Linux are totally different. On Linux if socket handle VALUE is bigger than FD_SETSIZE, there will be overrun issue on Linux version FD_SET macro. I make a workaround to alloc enough buffer for fd_set on Linux. such as,
char rsetBuffer[10240];
memset(rsetBuffer,0,10240);
fd_set& rset=(fd_set&)rsetBuffer;
FD_ZERO(&rset);
FD_SET(socketHandle, &rset);
p.s. Definition of fd_set struct and FD_SET macro on windows and Linux:
on windows:
typedef struct fd_set {
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;
#define FD_SET(fd, set) do { \
u_int __i; \
for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
if (((fd_set FAR *)(set))->fd_array[__i] == (fd)) { \
break; \
} \
} \
if (__i == ((fd_set FAR *)(set))->fd_count) { \
if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \
((fd_set FAR *)(set))->fd_array[__i] = (fd); \
((fd_set FAR *)(set))->fd_count++; \
} \
} \
} while(0)
on Linux:
/* fd_set for select and pselect. */
typedef struct
{
/* XPG4.2 requires this member name. Otherwise avoid the name
from the global namespace. */
#ifdef __USE_XOPEN
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
} fd_set;
#define __FD_SET(d, set) \
((void) (__FDS_BITS (set)[__FD_ELT (d)] |= __FD_MASK (d)))
#define __FD_CLR(d, set) \
((void) (__FDS_BITS (set)[__FD_ELT (d)] &= ~__FD_MASK (d)))
#define __FD_ISSET(d, set) \
((__FDS_BITS (set)[__FD_ELT (d)] & __FD_MASK (d)) != 0)
I'm currently working on a project using sockets via WinSock and have come across a peculiar problem. I'll attach the code before I start explaining.
#include "Connection.h"
Connection::Connection(SOCKET sock, int socketType)
: m_sock(sock), m_recvCount(0), m_sendCount(0), m_socketType(socketType)
{
printf("Succesfully created connection\n");
}
Connection::~Connection(void)
{
printf("Closing socket %d", m_sock);
closesocket(m_sock);
}
void Connection::ProcessMessage(const NetMessage *message){
printf("Got network message: type %d, data %s\n", message->type, message->data);
}
bool Connection::ReadSocket(){
// Call this when the socket is ready to read.
// Returns true if the socket should be closed.
// used to store count between the sockets
int count = 0;
if(m_socketType == SOCK_STREAM){
// attempt to read a TCP socket message
// Receive as much data from the client as will fit in the buffer.
count = recv(m_sock, &m_recvBuf[m_recvCount], sizeof(m_recvBuf) - m_recvCount, 0);
}
else if(m_socketType == SOCK_DGRAM){
// attempt to read UDP socket message
// temporarily stores details of the address which sent the message
// since UDP doesn't worry about whether it's connected to the
// sender or not
sockaddr_in fromAddr;
int fromAddrSize = sizeof(fromAddr);
count = recvfrom(m_sock, &m_recvBuf[m_recvCount], sizeof(m_recvBuf) - m_recvCount, 0, (sockaddr*) &fromAddr, &fromAddrSize);
}
else{
printf("Unknown socket type %d\n", m_socketType);
return true;
}
if (count <= 0)
{
printf("Tried to receive on socket %d and got %d bytes\n", m_sock, count);
printf("Client connection closed or broken\n");
return true;
}
// if we get to this point we have essentially received a complete message
// and must process it
printf("Received %d bytes from the client (total %d)\n", count, m_recvCount);
m_recvCount += count;
// Have we received a complete message?
// if so, process it
if (m_recvCount == sizeof NetMessage)
{
ProcessMessage((const NetMessage *) m_recvBuf);
m_recvCount = 0;
}
return false;
}
bool Connection::WriteSocket(){
// Sends the data in the send buffer through the socket
int count;
if(m_socketType == SOCK_STREAM){
// attempt to read TCP socket message
count = send(m_sock, m_sendBuf, m_sendCount, 0);
}
else if(m_socketType == SOCK_DGRAM){
// attempt to read UDP socket message
count = sendto(m_sock, m_sendBuf, m_sendCount, 0, 0, 0);
}
else{
// unhandled type of socket, kill server
printf("Unknown socket type %d", m_socketType);
return true;
}
if (count <= 0)
{
// we have received an error from the socket
printf("Client connection closed or broken\n");
return true;
}
m_sendCount -= count;
printf("Sent %d bytes to the client (%d left)\n", count, m_sendCount);
printf("Data: %s", m_sendBuf);
// Remove the sent data from the start of the buffer.
memmove(m_sendBuf, &m_sendBuf[count], m_sendCount);
return false;
}
bool Connection::WantWrite(){
if(m_sendCount > 0){
return true;
}
return false;
}
bool Connection::WantRead(){
return true;
}
bool Connection::SetMessage(const NetMessage *message){
// store contents of the message in the send buffer
// to allow us to send later
if (m_sendCount + sizeof(NetMessage) > sizeof(m_sendBuf))
{
return true;
}
memcpy(&m_sendBuf, message, sizeof(message));
m_sendCount += sizeof(NetMessage);
return false;
}
and the protocol
/* Definitions for the network protocol that the client and server use to communicate */
#ifndef PROTOCOL_H
#define PROTOCOL_H
// Message types.
enum MessageType
{
MT_UNKNOWN = 0,
MT_WELCOME = 1,
MT_KEYPRESS = 2,
MT_CHATMESSAGE = 3
};
// The message structure.
// This is a "plain old data" type, so we can send it over the network.
// (In a real program, we would want this structure to be packed.)
struct NetMessage
{
MessageType type;
char* data;
NetMessage()
: type(MT_UNKNOWN)
{
}
};
#endif
Essentially the protocol holds the definition of the messages that the client and server throw around to each other. The problem I am having is that, in connection.cpp line 132 (memcpy), the message becomes garbled in sendBuf.
http://imgur.com/MekQfgm,9ShRtHi
The image above shows exactly what is happening. As said in protocol.h the struct is a POD so when I do memcpy it should transfer the number of bytes as is held in the struct (so for example the message type should be 1 byte, followed by 7 or 8 bytes of data, in the example).
Can anyone shed some light on this? It's driving me crazy.
The line you wrote will copy 4 bytes (sizeof(pointer)) on 32bit systems:
memcpy(&m_sendBuf, message, sizeof(message));
what you probably meant is:
memcpy(&m_sendBuf, message, sizeof(NetMessage));
Edit:
In addition, as a commenter remarked, your data type is NOT a POD. It holds a pointer. You transfer that pointer. At the target system, it will point to the same place in RAM, but there will not be anything there. You need to actually make your datatype a POD by using an array or you need to find a way to transfer the data pointed to. You can achieve this by transfering the type, a length and a number of characters. That means that your receiver can NOT rely on messages being of fixed size.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Want to know the ESSID of wireless network via C++ in UBUNTU
Hello I have written the following code which is a part of a project. It is used to find the ESSID of the current associated network. But it has a flaw that it also the displays the ESSID of the network with which I am not associated i.e. if I try to associate myself with a wireless n/w and if it is unsuccessfull i.e. NO DHCP OFFERS ARE RECEIVED, then also it will display the that ESSID with which I have made my attempt.
Is it possible to find the BSSID of current associated wireless network as it is the only way with which I can mark b/w associated and non associated, e.g. with an ioctl call?
int main (void)
{
int errno;
struct iwreq wreq;
CStdString result = "None";
int sockfd;
char * id;
char ESSID[20];
memset(&wreq, 0, sizeof(struct iwreq));
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Cannot open socket \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description is : %s\n",strerror(errno));
return result ;
}
CLog::Log(LOGINFO,"Socket opened successfully");
FILE* fp = fopen("/proc/net/dev", "r");
if (!fp)
{
// TBD: Error
return result;
}
char* line = NULL;
size_t linel = 0;
int n;
char* p;
int linenum = 0;
while (getdelim(&line, &linel, '\n', fp) > 0)
{
// skip first two lines
if (linenum++ < 2)
continue;
p = line;
while (isspace(*p))
++p;
n = strcspn(p, ": \t");
p[n] = 0;
strcpy(wreq.ifr_name, p);
id = new char[IW_ESSID_MAX_SIZE+100];
wreq.u.essid.pointer = id;
wreq.u.essid.length = 100;
if ( ioctl(sockfd,SIOCGIWESSID, &wreq) == -1 ) {
continue;
}
else
{
strcpy(ESSID,id);
return ESSID;
}
free(id);
}
free(line);
fclose(fp);
return result;
}
Note: Since this question seems to be duplicated in two places, I'm repeating my answer here as well.
You didn't mention whether you were using an independent basic service set or not (i.e., an ad-hoc network with no controlling access point), so if you're not trying to create an ad-hoc network, then the BSSID should be the MAC address of the local access point. The ioctl() constant you can use to access that information is SIOCGIWAP. The ioctl payload information will be stored inside of your iwreq structure at u.ap_addr.sa_data.
ListenSocket.h
// class does not contain WSASTARTUP () and WSACLEANUP ()
#ifndef LISTENTHREAD_H
#define LISTENTHREAD_H
#include "includes.h"
#include "LOGMSGs.h"
// 1, CListenSocket: class is used to create the listener thread local variable.
// This class can be reused. When you call Close () is closed, re-calling Open () the new listening port. But the system did not use the feature.
class CListenSocket
{
public:
// main method:
// BIND each object only to a port.
CListenSocket(u_short nPort, int nSndSize = 0);
// to release SOCKET
~CListenSocket(){};
// Create server listening SOCKET, specific options see the code. Fails to return false.
bool Open(); // call can be repeated
// error return INVALID_SOCKET
SOCKET Accept(u_long & nClientIP);
// repeated calls. Usually not, can be used to take the initiative to close the SOCKET.
// close the re-call after Open () re-use the object.
void Close(); // call can be repeated
bool IsOpen() { return m_bState; }
bool Rebuild();
public:
SOCKET Socket() { return m_sockListen; }
protected:
// main member variables:
const u_short m_nPort;
const int m_nSndBuf;
SOCKET m_sockListen;
// network status is normal sign.
// When the value is false that the object is not available. May not have Open (), may also be a network error.
bool m_bState;
time_t m_tCloseTime; // SOCKET last closed the time delay for the automatic re-SOCKET
};
#endif // LISTENTHREAD_H
ListenSocket.cpp
#include "ListenSocket.h"
long s_nSocketCount = 0;
int REBUILDLISTENDELAYSEC;
CListenSocket::CListenSocket(u_short nPort, int nSndBuf /*= 0*/) // 0: Default
: m_nPort(nPort), m_nSndBuf(nSndBuf)
{
m_sockListen = INVALID_SOCKET;
m_bState = false;
// m_nPort = nPort;
m_tCloseTime = 0;
}
// Error returned INVALID_SOCKET
SOCKET CListenSocket::Accept(u_long & nClientIP)
{
/*
// Reconstruction SOCKET
if(!m_bState)
{
if(clock() < m_tCloseTime + REBUILDLISTENDELAYSEC*CLOCKS_PER_SEC)
return INVALID_SOCKET;
else
{
LOGMSG("Anti-crash system start listening SOCKET [%d] re under construction...", m_nPort);
if(Open())
{
LOGMSG("... listen SOCKET reconstruction success.");
PrintText("Listen SOCKET [%d] failed to rebuild SOCKET success. Server continues to run in the ...", m_nPort);
}
else
{
Error("... listen SOCKET reconstruction has failed. Server will not accept new connections");
PrintText("Listen SOCKET [%d] error, [%d] seconds after the re-SOCKET. Server continues to run in the ...", m_nPort, REBUILDLISTENDELAYSEC); // nDelaySec);
}
m_tCloseTime = clock();
}
}
//*/
if(!m_bState)
{
Error("ACCEPT inner exception a1");
return INVALID_SOCKET;
}
// ACCEPT
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
int len = sizeof(addr);
SOCKET newsock = accept(m_sockListen, (sockaddr*)&addr, (int*)&len); // receive to the other side of the map, you can use
#ifdef PROFILE_X
// Analysis Accept speed (cycle speed)
const int nTimes2 = ACCEPTPROFILESEC; // Statistics once every 30 seconds the speed ACCEPT
static clock_t tNextTime2 = clock() + nTimes2 * CLOCKS_PER_SEC; //? Only one monitor thread, no sharing violation
static long nCount2 = 0; //? Only one monitor thread, no sharing violation
if(clock() >= tNextTime2)
{
PrintText("Each [%d] seconds to execute a [%d] times Accept ()", nTimes2, InterlockedExchange(&nCount2, 0));
tNextTime2 = clock() + nTimes2 * CLOCKS_PER_SEC;
}
else
{
InterlockedIncrement(&nCount2);
}
#endif // PROFILE
if(newsock == INVALID_SOCKET)
{
// Network Error
int err = WSAGetLastError();
if(err != WSAEWOULDBLOCK)
{
PrintText("Listen SOCKET %d failed, %s seconds after the re-SOCKET.", m_nPort, REBUILDLISTENDELAYSEC);
Error("Listen SOCKET [%d] failed [%d], [%s] seconds after the re-SOCKET.", m_nPort, err, REBUILDLISTENDELAYSEC);
Close();
}
else
Error("ACCEPT inner exception a2");
return INVALID_SOCKET;
}
else
{
nClientIP = addr.sin_addr.S_un.S_addr;
InterlockedIncrement(&s_nSocketCount);
}
// Check whether the SOCKET closed
fd_set readmask;
FD_ZERO(&readmask);
FD_SET(newsock, &readmask);
struct timeval timeout = {0, 0};
/*
char nTemp;
if(select(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) 0, &timeout)
&& recv(newsock, &nTemp, 1, MSG_PEEK) == 0)
{
#ifdef ALPHA_X
LOGMSG("ACCEPT a new SOCKET is invalid .");
#endif
closesocket(newsock);
InterlockedDecrement(&s_nSocketCount);
return INVALID_SOCKET;
}
//else*/
//*
fd_set exceptmask;
FD_ZERO(&exceptmask);
FD_SET(newsock, &exceptmask);
int ret = select(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) &exceptmask, &timeout);
if(ret < 0)
{
Error("ACCEPT a new SOCKET is invalid . can't read"); // Not trigger
closesocket(newsock);
InterlockedDecrement(&s_nSocketCount);
return INVALID_SOCKET;
}
else if(ret > 0)
{
if(FD_ISSET(newsock, &exceptmask))
{
LOGMSG("ACCEPT a new SOCKET is invalid.except"); // Not trigger
closesocket(newsock);
InterlockedDecrement(&s_nSocketCount);
return INVALID_SOCKET;
}
else if(FD_ISSET(newsock, &readmask))
{
char nTemp;
if(recv(newsock, &nTemp, 1, MSG_PEEK) == 0)
{
#ifdef ALPHA_X
LOGMSG("ACCEPT a new SOCKET is invalid. recv==0"); // Not trigger
#endif
closesocket(newsock);
InterlockedDecrement(&s_nSocketCount);
return INVALID_SOCKET;
}
}
}
//*/
#ifdef PROFILE_X
// analysis Accept speed (received valid SOCKET)
const int nTimes = ACCEPTPROFILESEC; // Statistics once every 10 seconds the speed ACCEPT
static clock_t tNextTime = clock() + nTimes * CLOCKS_PER_SEC; //? Only one monitor thread, no sharing violation
static long nCount = 0; //? Only one monitor thread, no sharing violation
if(clock() >= tNextTime)
{
LOGPROFILE("Port [%d] for every [%d] seconds, the successful implementation of the [%d] times Accept()",
m_nPort, nTimes, InterlockedExchange(&nCount, 0));
tNextTime = clock() + nTimes * CLOCKS_PER_SEC;
}
else
{
InterlockedIncrement(&nCount);
}
#endif // PROFILE
return newsock;
}
Main.cpp
#include "includes.h"
#include "IniFile.h"
#include "LOGMSGs.h"
#include "ListenSocket.h"
CListenSocket Sock(9985);
int main()
{
Sock.Open();
if(!Sock.Open())
{
Sock.Rebuild();
}
if(Sock.IsOpen())
PrintText("okey");
Sock.Socket();
u_long ip;
Sock.Accept(ip);
}
but i always got this error : ACCEPT inner exception a2 while it should work anyclue why?
CListenSocket Sock(9985);
int main()
{
Sock.Open();
if(!Sock.Open())
/* I think you meant 'IsOpen()' */
{
Sock.Rebuild();
}
if(Sock.IsOpen())
PrintText("okey");
Sock.Socket();
u_long ip;
Sock.Accept(ip);
}
Incidentally, this code sure reads funny. It feels like a generic toolkit programmed without a specific goal in mind. Maybe I'm missing it, but I have to think you'd have better results if you just wrote the network code that actually needed, and then abstract out the common bits into some helper routines later. There's no point in trying too hard to make the be-all and end-all network helper library, but there is a huge point in making tools that collapse common cases.
Feel free to ignore that last paragraph if you know what you're doing :) but if you're just starting out, I'd like to suggest writing a few smaller clients and servers, and then try writing your abstraction layer.