《Tcp/Ip网络编程》第9章 - C/C++教程

      最后更新:2022-01-09 05:08:13 手机定位技术交流文章

      第9章:TCP/IP网络方案拟订

      • 套接字可选项
      • SO_REUSEADDR
      • TCP_NODELAY
      • Windows实现

      套接字可选项

      #include <sys/socket.h>
      //成功0,失败-1
      int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
      //成功0,失败-1
      int setsockopt(int sock, int level, int optname, const void *optval, socklen_t *optlen);
      

      sock_type.c

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <sys/socket.h>
      
      void error_handling(char *message);
      
      int main(int argc, char *argv[]) {
      	int tcp_sock;
      	int udp_sock;
      	int sock_type;
      	socklen_t optlen;
      	int state;
      
      	optlen = sizeof(sock_type);
      	tcp_sock = socket(PF_INET, SOCK_STREAM, 0);
      	udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
      	printf("SOCK_STREAM: %dn", SOCK_STREAM);
      	printf("SOCK_DGRAM: %dn", SOCK_DGRAM);
      
      	state = getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)sock_type, &optLen);
      	if(state)
      		error_handling("getsockopt() error");
      	printf("Socket type one: %dn", sock_type);
      	
      	state = getsockopt(udp_sock, SOL_SOCKET, SO_TYPE, (void*)sock_type, &optLen);
      	if(state)
      		error_handling("getsockopt() error");
      	printf("Socket type two: %dn", sock_type);
      	return 0;
      }
      
      
      void error_handling(char *message) {
      	fputs(message, stderr);
      	fputc('n', stderr);
      	exit(1);
      }
      
      gcc sock_type.c -o socktype
      ./socktype
      

      get_buf.c

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <sys/socket.h>
      
      void error_handling(char *message);
      
      int main(int argc, char *argv[]) {
      	int sock;
      	int snd_buf;
      	int rcv_buf;
      	int state;
      	socklen_t len;
      
      	sock = socket(PF_INET, SOCK_STREAM, 0);
      	len = sizeof(snd_buf);
      
      	//输出缓冲大小
      	state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)snd_buf, &len);
      	if(state)
      		error_handling("getsockopt() error");
      	printf("Input buffer size: %dn", rcv_buf);	
      		
      	//输入缓冲大小
      	state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)rcv_buf, &len);
      	if(state)
      		error_handling("getsockopt() error");
      	printf("Output buffer size: %dn", snd_buf);	
      	
      	return 0;
      }
      
      
      void error_handling(char *message) {
      	fputs(message, stderr);
      	fputc('n', stderr);
      	exit(1);
      }
      
      gcc get_buf.c -o getbuf
      ./getbuf
      

      set_buf.c

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <sys/socket.h>
      
      void error_handling(char *message);
      
      int main(int argc, char *argv[]) {
      	int sock;
      	int snd_buf=1024*3;
      	int rcv_buf=104*3;
      	int state;
      	socklen_t len;
      
      	sock = socket(PF_INET, SOCK_STREAM, 0);
      	state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)snd_buf, sizeof(snd_buf));
      	if(state)
      		error_handling("setsockopt() error");
      	state = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)rcv_buf, sizeof(rcv_buf));
      	if(state)
      		error_handling("setsockopt() error");
      
      	len = sizeof(snd_buf);
      
      	//输出缓冲大小
      	state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)snd_buf, &len);
      	if(state)
      		error_handling("getsockopt() error");
      	printf("Input buffer size: %dn", rcv_buf);	
      		
      	//输入缓冲大小
      	state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)rcv_buf, &len);
      	if(state)
      		error_handling("getsockopt() error");
      	printf("Output buffer size: %dn", snd_buf);	
      	
      	return 0;
      }
      
      void error_handling(char *message) {
      	fputs(message, stderr);
      	fputc('n', stderr);
      	exit(1);
      }
      
      gcc set_buf.c -o setbuf
      ./setbuf
      

      SO_REUSEADDR

      启动初始断开(通过发送FIN电文)的东道主已到达等待时间状态(设定延迟释放,以保证对方收到最后的ACK电文),此时相关港口已投入运行。

      reuseaddr_eserver.c

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <unistd.h>
      #include <arpa/inet.h>
      #include <sys/socket.h>
      
      #define TRUE 1
      #define FALSE 0
      void error_handling(char *message);
      
      int main(int argc, char *argv[]) {
      	int serv_sock;
      	int clnt_sock;
      	char message[30];
      	int option;
      	int opt_len;
      	int str_len;
      
      	struct sockaddr_in serv_addr;
      	struct sockaddr_in clnt_addr;
      	socklen_t addr_size;
      
      	if(argc!=2) {
      		printf("Usage : %s <port>n", argv[0]);
      		exit(1);
      	}
      
      	serv_sock = socket(PF_INET, SOCK_STREAM, 0);
      	if(serv_sock==-1)
      		error_handling("socket() error");
      		
      	opt_len = sizeof(option);
      	optiont = TRUE;
      	setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&option, opt_len);
      
      	addr_size = sizeof(struct sockaddr_in);
      	
      	memset(&serv_addr, 0, addr_size);
      	serv_addr.sin_family = AF_INET;
      	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      	serv_addr.sin_port = htons(atoi(argv[1]));
      	
      	if(bind(serv_sock, (struct sockaddr*)&serv_addr, addr_size)==-1)
      		error_handling("bind() error");
      		
      	if(listen(serv_sock, 5)==-1)
      		error_handling("listen() error");
      		
      	for(i=0; i<5; i++) {
      		clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &addr_size );
      		if(clnt_sock==-1)
      			error_handling("accept() error");
      		else
      			printf("Connected client %dn", i+1);
      			
      		while((str_len=read(clnt_sock, message, BUF_SIZE))!=0)
      			write(clnt_sock, message, str_len);
      			
      		close(clnt_sock);
      	}
      	
      	close(serv_sock);
      	return 0;
      }
      
      
      void error_handling(char *message) {
      	fputs(message, stderr);
      	fputc('n', stderr);
      	exit(1);
      }
      
      gcc reuseaddr_eserver.c -o reserver
      ./reserver 9190
      //Connected client 1
      //Connected client 2
      //Connected client 3
      

      TCP_NODELAY

      • 在TCP蚊帐中,Nagle方法是默认使用的,目的是最大限度地扩大缓冲,直至收到ACK,避免数据集在网络上超载(影响传输)过多,并提高网络传输效率。

      • “ 大型文件数据” 选项应予删除, 以便可以提高传输速度, 类似于平行传输, 无需等待最后一个软件包获得 ACK 后再发送下一个软件包, 下一个软件包可以同时传送 。

      int opt_val=1;
      setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&opt_val, sizeof(opt_val));
      
      int opt_val;
      socklen_t opt_len=sizeof(opt_val);
      getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&opt_val, &opt_val);
      

      Windows实现

      #include <winsock2.h>
      //成功0,岩层误差
      int getsockopt(SOCKET sock, int level, int optname, char *optval, int *optlen);
      //成功0,失败-1
      int setsockopt(SOCKET sock, int level, int optname, const char *optval, int optlen);
      

      buf_win.c

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <winsock2.h>
      
      void ErrorHanding(char *message);
      
      int main(int argc, char *argv[]) {
      	WSADATA wsaData;
      	SPCKET sock;
      	int snd_buf=1024*3;
      	int rcv_buf=104*3;
      	int state;
      
      	if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
      		ErrorHanding("WSAStartup() error!");
      		
      	sock = socket(PF_INET, SOCK_STREAM, 0);
      	ShorSocketBufSize(sock);
      	
      	state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&snd_buf, sizeof(snd_buf));
      	if(state==SOCKET_ERROR)
      		error_handling("setsockopt() error");
      		
      	state = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_buf, sizeof(rcv_buf));
      	if(state==SOCKET_ERROR)
      		error_handling("setsockopt() error");
      		
      	ShorSocketBufSize(sock);
      	
      	closesocket(sock);
      	
      	WSACleanup();
      	return 0;
      }
      
      void ShorSocketBufSize(SOCKET sock) {
      	int snd_buf;
      	int rcv_buf;
      	int state;
      	int len;
      
      	len=sizeof(snd_buf);
      	state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&snd_buf, &len);
      	if(state==SOCKET_ERROR)
      		error_handling("getsockopt() error");
      	printf("Output buffer size: %dn", snd_buf);	
      		
      	len=sizeof(rcv_buf);
      	state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_buf, &len);
      	if(state==SOCKET_ERROR)
      		error_handling("getsockopt() error");
      	printf("Input buffer size: %dn", rcv_buf);	
      }
      
      void ErrorHanding(char *message) {
      	fputs(message, stderr);
      	fputc('n', stderr);
      	exit(1);
      }
      
      gcc buf_win.c -o buf_win
      ./buf_win
      

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/16018.html

          热门文章

          文章分类