学习计算机网络编程
一、思路和学习方法
??本文学习于:C语言技术网(www.freecplus.net),在 b 站学习于 C 语言技术网,并加以自己的一些理解和复现,如有侵权会删除。 ??接下来对网络编程继续深入学习。
二、网络编程继续深入
2.1 搭建多进程网络服务框架
??前置学习需要理解 linux 网络编程基础,linux 多线程,多进程的相关知识和使用。然后搭建一个多进程网络服务的框架。建立一个多进程的 socket 服务端,然后多个客户端都能和服务端进行通信。涉及到的是信号,多进程的相关知识。其实现原理是,服务端当接受到一个服务端的连接时,建立一个进程,对服务端进行服务,那么这个服务端就可以响应多个客户端。 ??这里程序的框架主要是在之前的封装以后的服务端和客户端 CTcpServer.cpp 和 CTcpClient.cpp 中改写,注意在服务端加入这两句,就能够对多个客户端进行响应。CTcpServer.cpp 代码如下,
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
class CTcpServer
{
public:
int m_listenfd;
int m_clientfd;
CTcpServer();
bool InitServer(int port);
bool Accept();
int Send(const void *buf,const int buflen);
int Recv(void *buf,const int buflen);
~CTcpServer();
};
int main()
{
signal(SIGCHLD, SIG_IGN);
CTcpServer TcpServer;
if (TcpServer.InitServer(5005)==false)
{ printf("TcpServer.InitServer(5051) failed,exit...\n"); return -1; }
while(true){
if (TcpServer.Accept() == false) { printf("TcpServer.Accept() failed,exit...\n"); return -1; }
if(fork() > 0){close(TcpServer.m_clientfd); continue;}
close(TcpServer.m_listenfd);
printf("客户端已连接。\n");
char strbuffer[1024];
while (1)
{
memset(strbuffer,0,sizeof(strbuffer));
if (TcpServer.Recv(strbuffer,sizeof(strbuffer))<=0) break;
printf("接收:%s\n",strbuffer);
strcpy(strbuffer,"ok");
if (TcpServer.Send(strbuffer,strlen(strbuffer))<=0) break;
printf("发送:%s\n",strbuffer);
}
printf("客户端已断开连接。\n");
exit(0);
}
}
CTcpServer::CTcpServer()
{
m_listenfd=m_clientfd=0;
}
CTcpServer::~CTcpServer()
{
if (m_listenfd!=0) close(m_listenfd);
if (m_clientfd!=0) close(m_clientfd);
}
bool CTcpServer::InitServer(int port)
{
m_listenfd = socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if (bind(m_listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )
{ close(m_listenfd); m_listenfd=0; return false; }
if (listen(m_listenfd,5) != 0 ) { close(m_listenfd); m_listenfd=0; return false; }
return true;
}
bool CTcpServer::Accept()
{
if ( (m_clientfd=accept(m_listenfd,0,0)) <= 0) return false;
return true;
}
int CTcpServer::Send(const void *buf,const int buflen)
{
return send(m_clientfd,buf,buflen,0);
}
int CTcpServer::Recv(void *buf,const int buflen)
{
return recv(m_clientfd,buf,buflen,0);
}
??需要注意的是添加的 while(true) 和 if(fork() < 0) continue; 还有 exit(0) 函数,exit() 在 #include <stdlib.h> 头文件中。如果没有上述语句,在客户端和服务端对接一次后,就结束了,其结果如下 ??加上述语句,服务端用多进程方式对服务端进行服务,结果如下, ??这样就完成了最最基础的框架。但是还需要改进。程序中加如以下程序signal(SIGCHLD, SIG_IGN); ,注意加入头文件 #include <signal.h> 是屏蔽子进程退出的信号,避免产生僵尸进程,其中,可以用
ps -ef | grep CTcpServer
查看僵尸进程,其中为 [CTcpServer] <defunct> 为僵尸进程。
僵尸进程就是子进程运行完,父进程没有回收资源,就叫僵尸进程,如果父进程结束,那子进程
也自然结束。
??还要关掉多余的 socket ,对于父进程来说,不用和客户端连接,要关掉 m_connfd 的 socket ;对于子进程来说,不用监听 socket ,要关掉 m_listened 的 socket ,因此加入程序,
if(fork() > 0){close(TcpServer.m_clientfd); continue;}
close(TcpServer.m_listenfd);
2.2 多进程服务程序的退出和资源释放
??freecplus 框架具体使用,参考 up 主博客来学习,网址如下: http://www.freecplus.net/9ebb8276265b404488a3415be224ed85.html ??用 Ctrl+C 关闭进程,是不合适,因此采用其他方法来完成。这里为了方便使用,把作者写的 freecplus 框架放入程序中,里面封装了通信的一般方法,直接调用就行,对于 TCP 通信方面可以查看前面的 TCP 封装类,和那里的是一样的。还有如何使用 freecplus 框架,可以看作者的网站,写的很清楚,我就不赘叙了。使用多进程服务程序的退出和资源释放,其中程序如下。 ??下面是使用 freecplus 框架写的关于多进程服务的退出和资源释放,是服务端程序 ExitAndFreeServer.cpp,
#include "_freecplus.h"
CTcpServer TcpServer;
void FathEXIT(int sig);
void ChldEXIT(int sig);
int main(int argc, char *argv[]){
for(int ii = 0; ii <= 64; ii++) signal(ii, SIG_IGN);
signal(SIGINT, FathEXIT); signal(SIGTERM, FathEXIT);
if(TcpServer.InitServer(5005) == false){
printf("TcpServer.InitServer(5005) failed. \n"); FathEXIT(-1);
}
while(true){
if(TcpServer.Accept() == false){
printf("TcpServer.Accept() failed. \n"); continue;
}
if(fork() > 0){TcpServer.CloseClient(); continue; }
signal(SIGINT, ChldEXIT); signal(SIGTERM, ChldEXIT);
TcpServer.CloseListen();
printf("客户端(%s)已连接。 \n", TcpServer.GetIP());
char strbuffer[1024];
while(true){
memset(strbuffer, 0, sizeof(strbuffer));
if(TcpServer.Read(strbuffer, 10) == false) break;
printf("接收:%s \n", strbuffer);
strcat(strbuffer, "ok");
printf("发送:%s \n", strbuffer);
if(TcpServer.Write(strbuffer) == false)break;
}
printf("客户端已断开。 \n");
ChldEXIT(-1);
}
}
void FathEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN);signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);
printf("catching the signal(%d). \n", sig);
}
kill(0, 15);
printf("父进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
void ChldEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN);signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);
}
printf("子进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
??下面是使用 freecplus 框架写的关于多进程客户端程序,程序文件名是 freecplusClient.cpp ,其中程序如下,
#include "_freecplus.h"
CTcpClient TcpClient;
int main(int argc, char *argv[]){
if (TcpClient.ConnectToServer("127.0.0.1",5005) == false)
{ printf("TcpClient.ConnectToServer(\"127.0.0.1\",5005) failed,exit...\n"); return -1; }
char strbuffer[1024];
for (int ii=0;ii<5;ii++)
{
memset(strbuffer,0,sizeof(strbuffer));
snprintf(strbuffer,50,"%d: 这是第%d个超级女生,编号%03d。",getpid(),ii+1,ii+1);
printf("发送:%s\n",strbuffer);
if (TcpClient.Write(strbuffer) == false) break;
memset(strbuffer,0,sizeof(strbuffer));
if (TcpClient.Read(strbuffer,20) == false) break;
printf("接收:%s\n",strbuffer);
sleep(1);
}
}
??其中 makefile 文件如下
all:ExitAndFreeServer freecplusClient
ExitAndFreeServer:ExitAndFreeServer.cpp
g++ -g -o ExitAndFreeServer ExitAndFreeServer.cpp _freecplus.cpp
freecplusClient:freecplusClient.cpp
g++ -g -o freecplusClient freecplusClient.cpp _freecplus.cpp
??记住,使用查看进程的 linux 指令为,
ps -ef | grep ExitAndFree(文件名)
??然后让他们进行通信,两个客户端与服务端通信,然后观察运行效果, ??当使用 ps 查看进程号,然后用 kill 杀死进程时候,服务端程序显示如下, ??当使用 ctrl + c 结束进程时,显示如下, ??可以看出,是成功完成上述要求功能的。
2.3 多进程服务程序的日志
??日志模块对于一个程序而言是必不可少的,对于服务端程序更重要。因为几乎所有服务端程序都是作为守护进程而运行的,依靠日志记录关键信息就很重要了,当然日志的作用远不止记录信息,它还可以用于恢复。本文中,依旧使用作者的 freecplus 开发框架,注意 CLogFile logfile 已经封装在 _freecplus.h 里面,具体的可以查看源代码,其中服务端程序为,
#include "_freecplus.h"
CLogFile logfile;
CTcpServer TcpServer;
void FathEXIT(int sig);
void ChldEXIT(int sig);
int main(int argc, char *argv[]){
if(argc != 3){
printf("Using:./ExitAndFreeServer port logfile\nExample:./ExitAndFreeServer 5005 /tmp/ExitAndFreeServer.log\n\n"); return -1;
}
for(int ii = 0; ii <= 64; ii++) signal(ii, SIG_IGN);
if(logfile.Open(argv[2], "a+") == false){
printf("logfile.OPen(%s) failed.\n", argv[2]); return -1;
}
signal(SIGINT, FathEXIT); signal(SIGTERM, FathEXIT);
if(TcpServer.InitServer(5005) == false){
logfile.Write("TcpServer.InitServer(5005) failed. \n"); FathEXIT(-1);
}
while(true){
if(TcpServer.Accept() == false){
logfile.Write("TcpServer.Accept() failed. \n"); continue;
}
if(fork() > 0){TcpServer.CloseClient(); continue; }
signal(SIGINT, ChldEXIT); signal(SIGTERM, ChldEXIT);
TcpServer.CloseListen();
printf("客户端(%s)已连接。 \n", TcpServer.GetIP());
char strbuffer[1024];
while(true){
memset(strbuffer, 0, sizeof(strbuffer));
if(TcpServer.Read(strbuffer, 10) == false) break;
printf("接收:%s \n", strbuffer);
strcat(strbuffer, "ok");
printf("发送:%s \n", strbuffer);
if(TcpServer.Write(strbuffer) == false)break;
}
printf("客户端已断开。 \n");
ChldEXIT(-1);
}
}
void FathEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN);signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);
logfile.Write("catching the signal(%d). \n", sig);
}
kill(0, 15);
logfile.Write("父进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
void ChldEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN);signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);
}
logfile.Write("子进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
??注意,跟踪日志的 linux 语句为,
tail -f /tmp/ExitAndFreeServer.log
??运行结果如下,
2.4 增加业务逻辑
??增加业务逻辑能够给客户端身份验证。业务报文的格式自定义,客户端与服务端协商好就可以,使用 xml ,增加可读性、可扩展性、容错性。举个例子,
客户端请求报文示例:
<bizcode>1</bizcode><username>wucz</username><password>p@ssw0rd</password>
服务端回应报文示例:
<retcode>0</retcode><message>成功。</message>
<retcode>-1</retcode><message>用户名或密码不正确。</message>
??下面例子要建立一个服务端设置密码,客户端要输入密码的方式,用XML来实现。其中客户端程序如下,
#include "_freecplus.h"
CLogFile logfile;
CTcpServer TcpServer;
void FathEXIT(int sig);
void ChldEXIT(int sig);
bool _main(const char *strrecvbuffer, char *strsendbuffer);
bool biz001(const char *strrecvbuffer, char *strsendbuffer);
int main(int argc, char *argv[]){
if(argc != 3){
printf("Using:./ExitAndFreeServer port logfile\nExample:./ExitAndFreeServer 5005 /tmp/ExitAndFreeServer.log\n"); return -1;
}
for(int ii = 0; ii < 100; ii++) signal(ii, SIG_IGN);
if(logfile.Open(argv[2], "a+") == false){
printf("logfile.Open(%s) failed.\n", argv[2]); return -1;
}
signal(SIGINT, FathEXIT); signal(SIGTERM, FathEXIT);
if(TcpServer.InitServer(5005) == false){
logfile.Write("TcpServer.InitServer(5005) failed. \n"); FathEXIT(-1);
}
while(true){
if(TcpServer.Accept() == false){
logfile.Write("TcpServer.Accept() failed. \n"); continue;
}
if(fork() > 0){TcpServer.CloseClient(); continue; }
signal(SIGINT, ChldEXIT); signal(SIGTERM, ChldEXIT);
TcpServer.CloseListen();
logfile.Write("客户端(%s)已连接。 \n", TcpServer.GetIP());
char strrecvbuffer[1024], strsendbuffer[1024];
while(true){
memset(strrecvbuffer, 0, sizeof(strrecvbuffer));
memset(strsendbuffer, 0, sizeof(strsendbuffer));
if(TcpServer.Read(strrecvbuffer, 80) == false) break;
logfile.Write("接收:%s \n", strrecvbuffer);
if(_main(strrecvbuffer, strsendbuffer) == false) ChldEXIT(-1);
logfile.Write("发送:%s \n", strsendbuffer);
if(TcpServer.Write(strsendbuffer) == false) break;
}
logfile.Write("客户端已断开。 \n");
ChldEXIT(-1);
}
}
void FathEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN);
logfile.Write("catching the signal(%d). \n", sig);
}
kill(0, 15);
logfile.Write("父进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
void ChldEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN);signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);
}
logfile.Write("子进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
bool _main(const char * strrecvbuffer, char * strsendbuffer){
int ibizcode = -1;
GetXMLBuffer(strrecvbuffer, "bizcode", &ibizcode);
switch(ibizcode){
case 1:
biz001(strrecvbuffer, strsendbuffer); break;
default:
logfile.Write("非法报文:%s\n", strrecvbuffer); return false;
}
return true;
}
bool biz001(const char * strrecvbuffer, char * strsendbuffer){
char username[51], password[51];
memset(username, 0, sizeof(username));
memset(password, 0, sizeof(password));
GetXMLBuffer(strrecvbuffer, "username", username, 50);
GetXMLBuffer(strrecvbuffer, "password", password, 50);
if( (strcmp(username, "wucz") == 0) && (strcmp(password, "p@ssw0rd") == 0) )
sprintf(strsendbuffer, "<retcode>0</retcode><message>成功。</message>");
else
sprintf(strsendbuffer, "<retcode>-1</retcode><message>用户名或密码不正确。</message>");
return true;
}
??服务端运行如下,
#include "_freecplus.h"
CTcpClient TcpClient;
bool biz001();
int main(int argc, char *argv[]){
if(TcpClient.ConnectToServer("127.0.0.1", 5005) == false){
printf("TcpClient.ConnectToServer(\"127.0.0.1\", 5005) failed.\n"); return -1;
}
if(biz001() == false){
printf("biz001() failed.\n"); return -1;
}
}
bool biz001(){
char strbuffer[1024];
memset(strbuffer, 0, sizeof(strbuffer));
snprintf(strbuffer, 1000, "<bizcode>1</bizcode><username>wucz</username><password>p@ssw0rd</password>");
printf("发送:%s\n",strbuffer);
if (TcpClient.Write(strbuffer) == false) return false;
memset(strbuffer,0,sizeof(strbuffer));
if (TcpClient.Read(strbuffer,20) == false) return false;
printf("接收:%s\n", strbuffer);
int iretcode = -1;
GetXMLBuffer(strbuffer, "retcode", &iretcode);
if(iretcode == 0){printf("身份验证成功。\n"); return true;}
printf("身份验证失败。\n");
return false;
}
??运行结果如下,可以看到已经建立好了连接, ??运行结果如下,可以看到已经建立好了连接。那样,框架就已经搭建好,然后在里面写业务就可以了,在 _main 中来实现,之用增加希望的业务就可以。
2.5 TCP 短连接和长连接
??client 与 server 建立连接进行通信,通信完成后释放连接,建立连接时需要 3 次握手,释放需要 4 次挥手,连接的建立和释放都需要时间, server 还有创建新进程或线程的开销。 ??短连接:client/server 间只需要进行一次或连续多次通信,通信完成后马上断开了。管理起来比较简单,不需要额外的控制手段。 ??长连接:client/server 间需要多次通信,通信的频率和次数不确定,所以 client 和 server 需要保持这个连接,常用的方法就是采用心跳机制。根据不同的应用场景采取不同的策略,选择合适的方法。
2.6 长连接的心跳机制
??采用 client 与 server 采用长连接,在连接空闲时,client 没若干秒向 server 发送一个心跳报文,server 也回复一个心跳保温,确认连接继续生效中。 ??如果 server 在约定的时间内没有收到 client 的任何报文,则认为客户端已掉线,就主动断开连接,释放资源。心跳报文在 60 s 之内,不要超过 120 s; ??客户端程序如下,
#include "_freecplus.h"
CLogFile logfile;
CTcpServer TcpServer;
void FathEXIT(int sig);
void ChldEXIT(int sig);
bool _main(const char *strrecvbuffer, char *strsendbuffer);
bool biz000(const char *strrecvbuffer, char *strsendbuffer);
bool biz001(const char *strrecvbuffer, char *strsendbuffer);
bool biz002(const char *strrecvbuffer, char *strsendbuffer);
int main(int argc, char *argv[]){
if(argc != 3){
printf("Using:./ExitAndFreeServer port logfile\nExample:./ExitAndFreeServer 5005 /tmp/ExitAndFreeServer.log\n\n"); return -1;
}
for(int ii = 0; ii <= 64; ii++) signal(ii, SIG_IGN);
if(logfile.Open(argv[2], "a+") == false){
printf("logfile.OPen(%s) failed.\n", argv[2]); return -1;
}
signal(SIGINT, FathEXIT); signal(SIGTERM, FathEXIT);
if(TcpServer.InitServer(5005) == false){
logfile.Write("TcpServer.InitServer(5005) failed. \n"); FathEXIT(-1);
}
while(true){
if(TcpServer.Accept() == false){
logfile.Write("TcpServer.Accept() failed. \n"); continue;
}
if(fork() > 0){TcpServer.CloseClient(); continue; }
signal(SIGINT, ChldEXIT); signal(SIGTERM, ChldEXIT);
TcpServer.CloseListen();
logfile.Write("客户端(%s)已连接。 \n", TcpServer.GetIP());
char strrecvbuffer[1024], strsendbuffer[1024];
while(true){
memset(strrecvbuffer, 0, sizeof(strrecvbuffer));
memset(strsendbuffer, 0, sizeof(strsendbuffer));
if(TcpServer.Read(strrecvbuffer, 30) == false) break;
logfile.Write("接收:%s \n", strrecvbuffer);
if(_main(strrecvbuffer, strsendbuffer) == false) ChldEXIT(-1);
logfile.Write("发送:%s \n", strsendbuffer);
if(TcpServer.Write(strsendbuffer) == false)break;
}
logfile.Write("客户端已断开。 \n");
ChldEXIT(-1);
}
}
void FathEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN);signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);
logfile.Write("catching the signal(%d). \n", sig);
}
kill(0, 15);
logfile.Write("父进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
void ChldEXIT(int sig){
if(sig > 0){
signal(sig, SIG_IGN);signal(SIGINT, SIG_IGN);signal(SIGTERM, SIG_IGN);
}
logfile.Write("子进程退出。 \n");
TcpServer.CloseClient();
exit(0);
}
bool _main(const char * strrecvbuffer, char * strsendbuffer){
int ibizcode = -1;
GetXMLBuffer(strrecvbuffer, "bizcode", &ibizcode);
switch(ibizcode){
case 0:
biz000(strrecvbuffer, strsendbuffer); break;
case 1:
biz001(strrecvbuffer, strsendbuffer); break;
case 2:
biz002(strrecvbuffer, strsendbuffer); break;
default:
logfile.Write("非法报文:%s\n", strrecvbuffer); return false;
}
return true;
}
bool biz001(const char * strrecvbuffer, char * strsendbuffer){
char username[51], password[51];
memset(username, 0, sizeof(username));
memset(password, 0, sizeof(password));
GetXMLBuffer(strrecvbuffer, "username", username, 50);
GetXMLBuffer(strrecvbuffer, "password", password, 50);
if( (strcmp(username, "wucz") == 0) && (strcmp(password, "p@ssw0rd") == 0) )
sprintf(strsendbuffer, "<retcode>0</retcode><message>成功。</message>");
else
sprintf(strsendbuffer, "<retcode>-1</retcode><message>用户名或密码不正确。</message>");
return true;
}
bool biz002(const char *strrecvbuffer, char *strsendbuffer){
char cardid[51];
memset(cardid, 0, sizeof(cardid));
GetXMLBuffer(strrecvbuffer, "cardid", cardid, 50);
if(strcmp(cardid, "62620000000001") == 0)
sprintf(strsendbuffer, "<retcode>0</retcode><message>成功。</message><ye>100.50</ye>");
else
sprintf(strsendbuffer, "<retcode>-1</retcode><message>卡号不存在。</message>");
return true;
}
bool biz000(const char *strrecvbuffer, char *strsendbuffer){
sprintf(strsendbuffer, "<retcode>0</retcode><message>成功。</message>");
return true;
}
??客户端程序如下,
#include "_freecplus.h"
CTcpClient TcpClient;
bool biz000();
bool biz001();
bool biz002();
int main(int argc, char *argv[]){
if(argc != 3){
printf("Using:./client ip port\n Example:./client 127.0.0.1 5005\n\n"); return -1;
}
if(TcpClient.ConnectToServer(argv[1], atoi(argv[2])) == false){
printf("TcpClient.ConnectToServer(\"%s\", %s) failed.\n", argv[1], argv[2]); return -1;
}
if(biz001() == false){
printf("biz001() failed.\n"); return -1;
}
sleep(10);
biz002();
sleep(5);
biz002();
for(int ii = 0; ii < 3; ii++){
if(biz000() == false) break;
sleep(31);
}
}
bool biz001(){
char strbuffer[1024];
memset(strbuffer,0,sizeof(strbuffer));
snprintf(strbuffer, 1000, "<bizcode>1</bizcode><username>wucz</username><password>p@ssw0rd</password>");
printf("发送:%s\n",strbuffer);
if (TcpClient.Write(strbuffer) == false) return false;
memset(strbuffer,0,sizeof(strbuffer));
if (TcpClient.Read(strbuffer,20) == false) return false;
printf("接收:%s\n",strbuffer);
int iretcode = -1;
GetXMLBuffer(strbuffer, "retcode", &iretcode);
if(iretcode == 0){printf("身份验证成功。\n"); return true;}
printf("身份验证失败。\n");
return false;
}
bool biz002(){
char strbuffer[1024];
snprintf(strbuffer, 1000, "<bizcode>2</bizcode><cardid>62620000000001</cardid>");
printf("发送:%s\n", strbuffer);
if(TcpClient.Write(strbuffer) == false) return false;
memset(strbuffer, 0, sizeof(strbuffer));
if(TcpClient.Read(strbuffer, 20) == false) return false;
printf("接收:%s\n", strbuffer);
int iretcode = -1;
GetXMLBuffer(strbuffer, "retcode", &iretcode);
if(iretcode == 0) {printf("查询余额成功。\n"); return true; }
printf("查询余额成功。\n");
return true;
}
bool biz000(){
char strbuffer[1024];
memset(strbuffer,0,sizeof(strbuffer));
snprintf(strbuffer, 1000, "<bizcode>0</bizcode>");
printf("发送:%s\n",strbuffer);
if (TcpClient.Write(strbuffer) == false) return false;
memset(strbuffer,0,sizeof(strbuffer));
if (TcpClient.Read(strbuffer,20) == false) return false;
printf("接收:%s\n",strbuffer);
return true;
}
??运行结果如下, ??通过每隔一段时间同客户端和服务端进行一次通信,这样检测是否还在连接。在运行完成之后,客户端断开了连接。
三、总结
??最近事情比较多,真的比较忙,不过也还在认真的学习网络编程基本知识,现在感觉学习还是比较囫囵吞枣的,只是调试运行成功,然后理解每个语句功能,在 freecplus 框架里的内容还没有认真的理解,后面过程继续深入理解。
|