环境:
Centos 6.5+gcc (GCC) 4.8.2+kernel 2.6.32+cmake version 2.8.12.2
实现效果:
采用UDP协议,做一个简单的time server.
服务端代码udp_server.cpp:
#include <netdb.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <memory.h> #include <signal.h> #include <time.h> #include <stdlib.h> #include <arpa/inet.h> int sockfd; //套接字 void sig_handler(int signo) { if (signo == SIGINT) { printf("Server close\n"); close(sockfd); exit(1); } } //输出客户端信息 void out_addr(struct sockaddr_in *clientaddr) { //将端口从网络字节序转换成主机字节序 int port = ntohs(clientaddr->sin_port); char ip[16]; memset(ip, 0, sizeof(ip)); //将ip地址从网络字节序转换成点分十进制 inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr, ip, sizeof(ip)); printf("client: %s(%d) connected\n", ip, port); } //和客户端进行通信 void do_service() { struct sockaddr_in clientaddr; socklen_t len = sizeof(clientaddr); char buffer[1024]; memset(buffer, 0, sizeof(buffer)); // 接收客户端的数据报文 if (recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientaddr, &len) < 0) { perror("recvfrom error"); } else { out_addr(&clientaddr); printf("client send into: %s\n", buffer); //向客户端发送数据报文 long int t = time(0); char *ptr = ctime(&t); size_t size = strlen(ptr) * sizeof(char); if (sendto(sockfd, ptr, size, 0, (struct sockaddr *)&clientaddr, len) < 0) { perror("sendto error"); } } } int main(int argc, char *argv[]) { if (argc < 2) { printf("usage: %s port\n", argv[0]); exit(1); } if (signal(SIGINT, sig_handler) == SIG_ERR) { perror("signal sigint error"); exit(1); } /*步骤1:创建socket*/ sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket error"); exit(1); } int ret; int opt = 1; //设置套接字选项 if ((ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)) { perror("setsockopt error"); exit(1); } /*步骤2:调用bind函数对socket和地址进行绑定*/ struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; //ipv4 serveraddr.sin_port = htons(atoi(argv[1])); //port serveraddr.sin_addr.s_addr = INADDR_ANY; //ip if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { perror("bind error"); exit(1); } /*步骤3:服务端和客户端进行双向通信*/ while (1) { do_service(); } return 0; }
服务端CMakeLists.txt:
cmake_minimum_required(VERSION 2.8) #project name project(socket_demo) set(CMAKE_CXX_COMPILER "g++") #set compiler for c++ language set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -pthread -lrt -D_GLIBCXX_USE_NANOSLEEP") #source files(can add source files manually) #set(SOURCE_FILES main.cpp ThostFtdcMdApi.h ThostFtdcTraderApi.h ThostFtdcUserApiDataType.h ThostFtdcUserApiStruct.h MdSpi.cpp MdSpi.h TdSpi.cpp TdSpi.h CTP_Manager.cpp CTP_Manager.h Login.h Order.cpp Order.h User.cpp User.h Utils.cpp Utils.h DBManager.h DBManager.cpp Trader.h Trader.cpp FutureAccount.h FutureAccount.cpp Strategy.h Strategy.cpp Algorithm.h Algorithm.cpp) #source directory(add source files automatically) aux_source_directory(. SOURCE_FILES) #set extern libraries #set(LIBRARIES libthostmduserapi.so libthosttraderapi.so libmongoclient.so libboost_thread.so libboost_system.so libboost_regex.so) #add execute file add_executable(udp_server ${SOURCE_FILES}) #add link library #target_link_libraries(quant_ctp_XTrader ${LIBRARIES})
客户端代码:
#include <netdb.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <stdio.h> #include <memory.h> #include <signal.h> #include <time.h> #include <stdlib.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { if (argc < 3) { printf("usage: %s ip port\n", argv[0]); exit(1); } /*步骤1:创建socket*/ int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket error"); exit(1); } /*步骤2:调用recvfrom和sendto等函数和服务器双向通信*/ struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; //ipv4 server_addr.sin_port = htons(atoi(argv[2])); //port inet_pton(AF_INET, argv[1], &server_addr.sin_addr.s_addr); //ip address if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("connect error"); exit(1); } char buffer[1024] = "hello gmqh!"; //向服务器发送数据报文 //发送方式1: /*if (sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("sendto error"); exit(1); }*/ //发送方式2: if (send(sockfd, buffer, sizeof(buffer), 0) < 0) { perror("send error"); exit(1); } else { //接受服务器端发送的数据报文 int size; memset(buffer, 0, sizeof(buffer)); if ((size = recv(sockfd, buffer, sizeof(buffer), 0)) < 0) { perror("recv error"); exit(1); } else { printf("%s", buffer); } } close(sockfd); return 0; }
客户端CMakeLists.txt:
cmake_minimum_required(VERSION 2.8) #project name project(socket_demo) set(CMAKE_CXX_COMPILER "g++") #set compiler for c++ language set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -pthread -lrt -D_GLIBCXX_USE_NANOSLEEP") #source files(can add source files manually) #set(SOURCE_FILES main.cpp ThostFtdcMdApi.h ThostFtdcTraderApi.h ThostFtdcUserApiDataType.h ThostFtdcUserApiStruct.h MdSpi.cpp MdSpi.h TdSpi.cpp TdSpi.h CTP_Manager.cpp CTP_Manager.h Login.h Order.cpp Order.h User.cpp User.h Utils.cpp Utils.h DBManager.h DBManager.cpp Trader.h Trader.cpp FutureAccount.h FutureAccount.cpp Strategy.h Strategy.cpp Algorithm.h Algorithm.cpp) #source directory(add source files automatically) aux_source_directory(. SOURCE_FILES) #set extern libraries #set(LIBRARIES libthostmduserapi.so libthosttraderapi.so libmongoclient.so libboost_thread.so libboost_system.so libboost_regex.so) #add execute file add_executable(udp_client ${SOURCE_FILES}) #add link library #target_link_libraries(quant_ctp_XTrader ${LIBRARIES})
编译方式:
cmake . make
运行效果:
文章的脚注信息由WordPress的wp-posturl插件自动生成