很早就做了这个例子,用来让别人测试网络服务器和客户端端口通信是否正常的(:-(),做的比较粗糙但是测试基本的socket通信还是可以的。代码是参考网络和APUE上的示例改写的,用MinGW或者VC编译。和之前java版本一样(java socket示例),也是将udp和tcp协议分开写,这样的好处就是想测哪个测哪个,当然了也就麻烦。
/*tcpc.cpp*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#include "mysock.h" #pragma comment(lib,"ws2_32.lib") int tcp_keep_alive(int ); int main(int argc,char* argv[]) { int sockfd,n; char recvline[MAXLINE + 1], sendline[MAXLINE]; #ifdef AF4 struct sockaddr_in servaddr; #else struct sockaddr_in6 servaddr; #endif if(argc != 3) { printf("%s\n","usage: tcpc <Server IP> <Server Port>"); return 0; } wsa_init(); bzero(&servaddr,sizeof(servaddr)); #ifdef AF4 RUN((sockfd=socket(AF_INET,SOCK_STREAM,0)), "socket"); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(atoi(argv[2])); RUN(inet_pton(AF_INET,argv[1],&servaddr.sin_addr), "inet_pton"); #else RUN((sockfd=socket(AF_INET6,SOCK_STREAM,0)),"socket"); servaddr.sin6_family = AF_INET6; servaddr.sin6_port = htons(atoi(argv[2])); RUN(inet_pton(AF_INET6,argv[1],&servaddr.sin6_addr), "inet_pton"); #endif RUN(connect(sockfd, (SA *)&servaddr, sizeof(servaddr)), "connect"); _snprintf(sendline, MAXLINE, "%s", "hello"); //if(write(sockfd, sendline, strlen(sendline)) < 0) RUN(send(sockfd, sendline, strlen(sendline), 0), "send"); /* while( (n = read(sockfd, recvline, MAXLINE)) > 0) { recvline[n] = 0; if(fputs(recvline, stdout) == EOF) err_exit("fputs"); if(n < 0) err_exit("read"); exit(0); } */ RUN(recv(sockfd, recvline, MAXLINE, 0), "recv"); fputs(recvline, stdout); closesocket(sockfd); //sleep(5); //sleep是为了完成tcp关闭的过程,否则会出现TIME_WAIT的状态 } |
/*tcps.cpp*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#include "mysock.h" #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) { int listenfd, connfd; int addrlen; #ifdef AF4 struct sockaddr_in servaddr, cliaddr; #else struct sockaddr_in6 servaddr, cliaddr; #endif char sendline[MAXLINE],recvline[MAXLINE]; time_t ticks; if(argc != 2) { printf("%s\n","usage: tcps <Server Port>"); return 0; } wsa_init(); bzero(&servaddr, sizeof(servaddr)); #ifdef AF4 listenfd = socket(AF_INET, SOCK_STREAM, 0 ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(atoi(argv[1])); #else listenfd = socket(AF_INET6, SOCK_STREAM, 0 ); servaddr.sin6_family = AF_INET6; //inet_pton(AF_INET6, "::1", &servaddr.sin6_addr); servaddr.sin6_addr = in6addr_any; servaddr.sin6_port = htons(atoi(argv[1])); #endif RUN(bind(listenfd, (SA *)&servaddr, sizeof(servaddr)), "bind"); RUN(listen(listenfd, 5), "listen"); addrlen = sizeof(cliaddr); for(;;) { RUN((connfd = accept(listenfd, (SA *)&cliaddr, &addrlen)), "accept"); //if(read(connfd, recvline, MAXLINE) < 0) RUN(recv(connfd, recvline, MAXLINE, 0), "recv"); ticks = time(NULL); _snprintf(sendline, sizeof(sendline), "%.24s\r\n", ctime(&ticks)); //if((write(connfd, sendline, strlen(sendline))) < 0) RUN(send(connfd, sendline, strlen(sendline), 0), "send"); closesocket(connfd); } } |
/*udpc.cpp*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include "mysock.h" #pragma comment(lib,"ws2_32.lib") int main(int argc,char* argv[]) { int sockfd,n; char sendline[MAXLINE], recvline[MAXLINE]; #ifdef AF4 struct sockaddr_in servaddr; #else struct sockaddr_in6 servaddr; #endif if(argc != 3) { printf("%s\n","usage: udpc <Server IP> <Server Port>"); return 0; } wsa_init(); bzero(&servaddr, sizeof(servaddr)); #ifdef AF4 RUN((sockfd = socket(AF_INET, SOCK_DGRAM, 0)),"socket"); servaddr.sin_family = AF_INET; if((inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0)) err_exit("inet_pton AF_INET"); servaddr.sin_port = htons(atoi(argv[2])); #else RUN((sockfd = socket(AF_INET6, SOCK_DGRAM, 0)), "socket"); servaddr.sin6_family = AF_INET6; RUN(inet_pton(AF_INET6, argv[1], &servaddr.sin6_addr), "inet_pton"); servaddr.sin6_port = htons(atoi(argv[2])); #endif _snprintf(sendline, MAXLINE, "%s", "hello"); RUN(sendto(sockfd, sendline, strlen(sendline), 0, (SA *)&servaddr, sizeof(servaddr)), "sendto"); RUN(recvfrom(sockfd, recvline, MAXLINE, 0 ,(SA *)NULL, NULL), "recvfrom"); fputs(recvline, stdout); closesocket(sockfd); } |
/*udps.cpp*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include "mysock.h" #pragma comment(lib,"ws2_32.lib") int main(int argc,char* argv[]) { int sockfd, n, addrlen; char sendline[MAXLINE],recvline[MAXLINE]; time_t ticks; if(argc != 2) { printf("%s\n","usage: udps <Server Port>"); return 0; } wsa_init(); #ifdef AF4 struct sockaddr_in servaddr, cliaddr; #else struct sockaddr_in6 servaddr, cliaddr; #endif bzero(&servaddr, sizeof(servaddr)); #ifdef AF4 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) err_exit("socket"); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* if((inet_pton(AF_INET, "::1", &servaddr.sin_addr) < 0)) err_exit("inet_pton AF_INET"); */ servaddr.sin_port = htons(atoi(argv[1])); #else if((sockfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) err_exit("socket"); servaddr.sin6_family = AF_INET6; /* if((inet_pton(AF_INET6, "::1", &servaddr.sin6_addr) < 0)) err_exit("inet_pton AF_INET6"); */ servaddr.sin6_addr = in6addr_any; //ipv6绑定所有地址要这么设置 servaddr.sin6_port = htons(atoi(argv[1])); #endif RUN(bind(sockfd,(SA *)&servaddr,sizeof(servaddr)), "bind"); addrlen = sizeof(cliaddr); for(;;) { RUN(recvfrom(sockfd, recvline, MAXLINE, 0 , (SA *)&cliaddr, &addrlen), "recvfrom"); //fputs(recvline, stdout); ticks = time(NULL); _snprintf(sendline, MAXLINE, "%.24s\r\n", ctime(&ticks)); RUN(sendto(sockfd, sendline, strlen(sendline), 0, (SA *)&cliaddr, sizeof(cliaddr)), "sendto"); } closesocket(sockfd); } |
还有一个mstcpip.h,都已经忘记是从哪里来的了,先记下来:
/*mstcpip.h*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// Copyright (c) Microsoft Corporation. All rights reserved. #if _MSC_VER > 1000 #pragma once #endif /* Argument structure for SIO_KEEPALIVE_VALS */ struct tcp_keepalive { u_long onoff; u_long keepalivetime; u_long keepaliveinterval; }; // New WSAIoctl Options #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1) #define SIO_RCVALL_MCAST _WSAIOW(IOC_VENDOR,2) #define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3) #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) #define SIO_ABSORB_RTRALERT _WSAIOW(IOC_VENDOR,5) #define SIO_UCAST_IF _WSAIOW(IOC_VENDOR,6) #define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7) #define SIO_INDEX_BIND _WSAIOW(IOC_VENDOR,8) #define SIO_INDEX_MCASTIF _WSAIOW(IOC_VENDOR,9) #define SIO_INDEX_ADD_MCAST _WSAIOW(IOC_VENDOR,10) #define SIO_INDEX_DEL_MCAST _WSAIOW(IOC_VENDOR,11) // Values for use with SIO_RCVALL* options #define RCVALL_OFF 0 #define RCVALL_ON 1 #define RCVALL_SOCKETLEVELONLY 2 |
还有两个粗陋的定义
/* mysock.h */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#ifndef __MYSOCK_H #define __MYSOCK_H #endif #include <Winsock2.h> #include <Ws2tcpip.h> //contain inet_pton() #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> #include <time.h> #define MAXLINE 4096 #define SA struct sockaddr #define AF4 /**/ #define RUN(A,B) if((A) < 0)err_exit(B) #define bzero(a, b) memset(a, 0, b) extern int wsa_init(void); extern void err_exit(char* msg); |
/* mysock.cpp */
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include "mysock.h" void err_exit(char *msg) { printf("%s: %d\n",msg,WSAGetLastError()); exit(1); } int wsa_init() { int err; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { printf("WSAStartup: %d\n",err=WSAGetLastError()); exit(err); } /* if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { printf("little or big error\n"); WSACleanup( ); exit(1); } */ return 0; } int tcp_keep_alive(int socketfd) { int keepAlive = 1; int keepIdle = 10; int keepInterval = 10; int keepCount = 10; if(setsockopt(socketfd,SOL_SOCKET,SO_KEEPALIVE,(char*)&keepAlive,sizeof(keepAlive)) == -1){ printf("setsockopt SIO_KEEPALIVE_VALS failed\n"); return -1; } return 0; } |
编译:
cl /MT /Fetcpc.exe tcpc.cpp mysock.cpp
cl /MT /Fetcps.exe tcps.cpp mysock.cpp
cl /MT /Feudpc.exe udpc.cpp mysock.cpp
cl /MT /Feudps.exe udps.cpp mysock.cpp
del *.obj
最近要换电脑了,整理资料的时候看到好几个目录下都保存了这份socket测试代码,对比之后,把最后日期的上传上来,只保留这份其他的都删除。印象中还有一个linux版本的,大概步骤一致,只是linux上更加简单,不必理会windows的封装,直接用源生的c接口。在虚拟机里还找到一份当时做的MFC的测试工具,都忘记曾经有这么个东西了,可惜源码不记得放在哪里,看来资料整理不好,也是很头疼的。