近来在做性能测试时,基于C/S模式,记录下Server/Client的模块代码,可直接挪用。
//< server.cpp
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int g_server = -1;
int g_client = -1;
void handle_close()
{
printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);
if (g_server > 0)
{
close(g_server);
g_server = -1;
}
if (g_client > 0)
{
close(g_client);
g_client = -1;
}
}
void handle_exit()
{
printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);
handle_close();
return;
}
void handle_signal(int signo)
{
printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);
if (signo == SIGINT)
{
handle_close(); exit(0);
}
}
int main(int args, char*argv[])
{
if (atexit(handle_exit) == -1)
{
fprintf(stderr, "atexit failed, strerror:%s\n", strerror(errno));
return -1;
}
if (signal(SIGINT, handle_signal) == SIG_ERR)
{
fprintf(stderr, "signal failed, strerror:%s\n", strerror(errno));
return -1;
}
if (args != 2)
{
//< argv[1]:svrPort
fprintf(stderr, "usage:./server 3456");
return -1;
}
struct sockaddr_in svrAddr;
struct sockaddr_in remoteAddr;
g_server = socket(AF_INET, SOCK_STREAM, 0);
if (g_server == -1)
{
fprintf(stderr, "create listen socket failed, svr(%s:%d)!\n", argv[1], atoi(argv[2]));
fprintf(stderr, "errno:%d, strerror:%s\n", errno, strerror(errno));
return -1;
}
svrAddr.sin_family = AF_INET;
svrAddr.sin_port = htons(atoi(argv[1]));
svrAddr.sin_addr.s_addr = INADDR_ANY;
bzero(&(svrAddr.sin_zero), 8);
if (-1 == bind(g_server, (struct sockaddr*)&svrAddr, sizeof(struct sockaddr)))
{
fprintf(stderr, "bind failed, errno:%d, strerror:%s\n", errno, strerror(errno));
return -1;
}
if (-1 == listen(g_server, 5))
{
fprintf(stderr, "listen failed, errno:%d, strerror:%s\n", errno, strerror(errno));
return -1;
}
socklen_t len = sizeof(struct sockaddr_in);
g_client = accept(g_server, (struct sockaddr*)&remoteAddr, &len);
if (-1 == g_client)
{
fprintf(stderr, "accept failed, errno:%d, strerror:%s\n", errno, strerror(errno));
return -1;
}
printf("succeed accept an client socket:%d\n", g_client);
//TODO: 通过g_client和客户端通信
return 0;
}
//< client.cpp
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int g_client = -1;
void handle_close()
{
printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);
if (g_client > 0)
{
close(g_client);
g_client = -1;
}
}
void handle_exit()
{
printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);
handle_close();
return;
}
void handle_signal(int signo)
{
printf("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);
if (signo == SIGINT)
{
handle_close(); exit(0);
}
}
int main(int args, char*argv[])
{
if (atexit(handle_exit) == -1)
{
fprintf(stderr, "atexit failed, strerror:%s\n", strerror(errno));
return -1;
}
if (signal(SIGINT, handle_signal) == SIG_ERR)
{
fprintf(stderr, "signal failed, strerror:%s\n", strerror(errno));
return -1;
}
if (args != 3)
{
//< argv[1]:svrIP, argv[2]:svrPort
fprintf(stderr, "usage:./client 127.0.0.1 3456");
return -1;
}
g_client = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == g_client)
{
fprintf(stderr, "create client socket failed!\n");
return -1;
}
struct sockaddr_in svrAddr;
bzero((void*)&svrAddr, sizeof(svrAddr));
svrAddr.sin_family = AF_INET;
svrAddr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET, argv[1], &svrAddr.sin_addr);
if (-1 == connect(g_client, (struct sockaddr*)&svrAddr, sizeof(svrAddr)))
{
fprintf(stderr, "connect to server(%s:%d) failed.\n", argv[1], atoi(argv[2]));
return -1;
}
printf("connect to server(%s:%d) succeed.\n", argv[1], atoi(argv[2]));
//TODO:通过g_client和server进行通信。
return g_client;
}
$make server
$make client
$server 3333 &
$client 127.0.0.1 3333
server和client遇到异常退出或者Ctrl+C被退出时,各自都可以安全清除所有的socket fd和断开所有的链接。
(END)