소스 검색

added seeking maximum receive buffer size

Jiri Kuthan 24 년 전
부모
커밋
d24a205903
2개의 변경된 파일72개의 추가작업 그리고 1개의 파일을 삭제
  1. 69 1
      udp_server.c
  2. 3 0
      udp_server.h

+ 69 - 1
udp_server.c

@@ -26,7 +26,13 @@ int udp_sock;
 int udp_init(unsigned long ip, unsigned short port)
 int udp_init(unsigned long ip, unsigned short port)
 {
 {
 	struct sockaddr_in* addr;
 	struct sockaddr_in* addr;
-	int optval;
+	int optval, optvallen;
+	int ioptval, ioptvallen;
+	int foptval, foptvallen;
+	int voptval, voptvallen;
+	int i;
+	int phase=0;
+
 
 
 	addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr));
 	addr=(struct sockaddr_in*)malloc(sizeof(struct sockaddr));
 	if (addr==0){
 	if (addr==0){
@@ -51,6 +57,68 @@ int udp_init(unsigned long ip, unsigned short port)
 		goto error;
 		goto error;
 	}
 	}
 
 
+	/* jku: try to increase buffer size as much as we can */
+	ioptvallen=sizeof(ioptval);
+	if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &ioptval,
+		    &ioptvallen) == -1 )
+	{
+		LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno));
+		goto error;
+	}
+	if ( ioptval==0 ) 
+	{
+		LOG(L_DBG, "DEBUG: udp_init: SO_RCVBUF initialy set to 0; resetting to %d\n",
+			BUFFER_INCREMENT );
+		ioptval=BUFFER_INCREMENT;
+	} else LOG(L_INFO, "INFO: udp_init: SO_RCVBUF is initially %d\n", ioptval );
+	for (optval=ioptval; optval < MAX_RECV_BUFFER_SIZE ;  ) {
+		/* increase size; double in initial phase, add linearly later */
+		if (phase==0) optval <<= 1; else optval+=BUFFER_INCREMENT;
+		LOG(L_DBG, "DEBUG: udp_init: trying SO_RCVBUF: %d\n", optval );
+        	if (setsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF,
+                             (void*)&optval, sizeof(optval)) ==-1)
+        	{
+			LOG(L_DBG, "DEBUG: udp_init: SOL_SOCKET failed for %d, phase %d: %s\n",
+			    optval,  phase, strerror(errno) );
+			/* if setting buffer size failed and still in the aggressive
+			   phase, try less agressively; otherwise give up 
+			*/
+			if (phase==0) { phase=1; optval >>=1 ; continue; } 
+			else break;
+        	} 
+		/* verify if change has taken effect */
+		voptvallen=sizeof(voptval);
+		if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &voptval,
+		    &voptvallen) == -1 )
+		{
+			LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno));
+			goto error;
+		} else {
+			LOG(L_DBG, "DEBUG: setting SO_RCVBUF; set=%d,verify=%d\n", 
+				optval, voptval);
+			if (voptval<optval) {
+				LOG(L_DBG, "DEBUG: setting SO_RCVBUF has no effect\n");
+				/* if setting buffer size failed and still in the aggressive
+			   	phase, try less agressively; otherwise give up 
+				*/
+                        	if (phase==0) { phase=1; optval >>=1 ; continue; } 
+                        	else break;
+			}
+		}
+
+	} /* for ... */
+	foptvallen=sizeof(foptval);
+	if (getsockopt( udp_sock, SOL_SOCKET, SO_RCVBUF, (void*) &foptval,
+		    &foptvallen) == -1 )
+	{
+		LOG(L_ERR, "ERROR: udp_init: getsockopt: %s\n", strerror(errno));
+		goto error;
+	}
+ 	LOG(L_INFO, "INFO: udp_init: SO_RCVBUF is finally %d\n", foptval );
+
+
+	/* EoJKU */
+
 	if (bind(udp_sock, (struct sockaddr*) addr, sizeof(struct sockaddr))==-1){
 	if (bind(udp_sock, (struct sockaddr*) addr, sizeof(struct sockaddr))==-1){
 		LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno));
 		LOG(L_ERR, "ERROR: udp_init: bind: %s\n", strerror(errno));
 		goto error;
 		goto error;

+ 3 - 0
udp_server.h

@@ -8,6 +8,9 @@
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
 
 
+#define MAX_RECV_BUFFER_SIZE	256*1024
+#define BUFFER_INCREMENT	2048
+
 extern int udp_sock;
 extern int udp_sock;
 
 
 int udp_init(unsigned long ip, unsigned short port);
 int udp_init(unsigned long ip, unsigned short port);