程序编写学习:C标准库编写网络程序方法学习



MFC类库为我们提供了“方便、好用”CAsyncSocket和CSocket但是MFC本身就是个迷宫进去不小心就出不来了像CAsyncSocket和CSocket它们是实现是很复杂里面实现异步消息是通过窗体消息机制来实现常常出现化时即使运行段时间也常常出现莫名其妙导致崩溃你不要以为是MFC问题MFC是绝对不会承认有时候你不得不采用逐行注释代码思路方法来确定什么地方导致这个过程是相当痛苦最后你还得为买单肯定是你编程但你又不知道错在哪儿
我有次编写录音功能网络接收到远程录音传输数据保存在内存中后来发现不定时在启动时候CSocket.Create出错都了N遍也不知道为什么关键是不定时调试也麻烦最后只好采用注释方式最终发现接收到录音数据保存到内容那段代码注释掉就好了我认真看了那段代码绝对没有内存溢出会导致覆盖掉CSocket每次接收数据总和也不会超过1M不可能把内容耗尽其实很多很成熟软件Software都有类似老版本迅雷也曾经出现过这种提示我忘了
用了CAsyncSocket后我下了决心以后决不用它了当然也不会用从它继承而来CSocket那就用C标准库SOCKET什么操作和都是掌握在自己手中没有了CAsyncSocket异步消息机制自己用线程来做网络编程多线程是第
经过长期实贱封装了如下SOCKET其实使用也挺简单:

1客户端:
#<stdlib.h>
#<winsock.h>
#<stdio.h>
#<.h>

#ndef INADDR_NONE
# INADDR_NONE 0xffffffff
#end

//******************************************************
//
//本负责和服务平台联系
//
//******************************************************

SOCKET SocketConnect(const char *host,const char *service,const char *transport)
{
struct protoent *protoin;//传输协议信息
struct sockaddr_in ipaddr;//主机IP地址信息
struct hostent *hostin;//主机信息
struct servent *servin;//服务器(主机)信息
sock,type;//套接字描述符

//将ipaddr结构快速清零
mem(&ipaddr,0,(ipaddr));
//地址结构
ipaddr.sin_family=AF_INET;

//从服务器类型得到端口号
(servin=getservbyname(service,transport))
ipaddr.sin_port=servin->s_port;//端口号
[Page]
((ipaddr.sin_port=htons((u_)atoi(service)))0)
{
prf(\"get server information error\\n\");
WSACleanup;


INVALID_SOCKET;
}
//由传输协议得到对应传输协议编码
((protoin=getprotobyname(transport))0)
{
prf(\"get protocol information error\\n\");
WSACleanup;
INVALID_SOCKET;
}
//从主机名获取主机IP
(hostin=gethostbyname(host))
memcpy(&ipaddr.sin_addr,hostin->h_addr,hostin->h_length);////

((ipaddr.sin_addr.s_addr=inet_addr(host))INADDR_NONE)
{
prf(\"get host IP infomation error\\n\");
[Page] WSACleanup;
INVALID_SOCKET;
}
//根据传输类型给变量赋值
(strcmp(transport,\"udp\")0)
type=SOCK_DGRAM;

type=SOCK_STREAM;
//创建套接字描述符
sock=(PF_INET,type,protoin->p_proto);
(sockINVALID_SOCKET)


{
prf(\"creat error\\n\");
WSACleanup;
INVALID_SOCKET;
}
[Page]
//连接指定IP地址机器指定服务端口如果连接失败则退出
(connect(sock,(struct sockaddr*)&ipaddr,(ipaddr))SOCKET_ERROR)
{
prf(\"connect error!please start server first\\n\");
WSACleanup;
INVALID_SOCKET;
}
sock;
}

//************************************
//UDP传输类型
//************************************
SOCKET UDPConnect(const char *host,const char *service)
{
SocketConnect(host,service,\"udp\");
}

//************************************
//TCP传输类型
//************************************
SOCKET TCPConnect(const char *host,const char *service)
{
SocketConnect(host,service,\"tcp\");
}

2客户端例子(TCP):
//启动后即连接服务器连接成功后接收控制台输入发送到服务端
#<stdio.h>
#<.h>
#<stdlib.h>
#<winsock.h>
#\"SocketConnect.h\"
#\"SendingControl.h\"
#pragma comment(lib,\"wsock32\")

#ndef INADDR_NONE
# INADDR_NONE 0xffffffff
#end



SOCKET TCPConnect(const char*,const char*);
void TCPecho(char *,char*);

# LINELEN 128
# WAVERS MAKEWORD(2,0)//WORD MAKEWORD( bLow, bHigh);

void ( argc,char *argv)
{
char *host=\"localhost\";//IP 地址
[Page] char *service=\"3333\";//默认端口号
WSADATA wsadata;
switch(argc)
{
1:
host=\"localhost\";//使用默认IP
;
2:
host=argv[1];//使用命令行给IP
;
3:
host=argv[1];
service=argv[2];//使用命令行IP和端口号
;
default:
prf(\"argment error\\n\");
exit(1);
}

(WSAStartup(WAVERS,&wsadata)!=0)//化Winsock
{
prf(\"initalize failed\\n\");
WSACleanup;//清除Winsock
exit(1);
}

TCPecho(host,service);

WSACleanup;
[Page]
exit(0);
}

void TCPecho(char *host,char *service)
{


char buf[LINELEN+1];
SOCKET s;
outchars;

s=TCPConnect(host,service);//采用TCP协议连接服务
while(fgets(buf,(buf),stdin))//循环得到用户输入,当输入数据为回车时退出
{
buf[LINELEN]=\'\\0\';
outchars=strlen(buf);
send(s,buf,outchars,0);//发送消息

(buf[0]\'\\n\')
;
}
close(s);
}

3服务端:
#<.h>
#<winsock.h>
#<stdlib.h>
#<stdio.h>
//
//SocketServer
//
SOCKET SocketServer(const char *service,const char*transport, qlen)
{
struct sockaddr_in ipaddr;//主机IP地址
struct servent *servin;// 主机信息
struct protoent *protoin;//传输类型
sock,type;// 套接字描述符

mem(&ipaddr,0,(ipaddr));
ipaddr.sin_family=AF_INET;
ipaddr.sin_addr.s_addr=INADDR_ANY;

// 从服务器名得到服务端口
(servin=getservbyname(service,transport))
ipaddr.sin_port=htons(ntohs((u_)servin->s_port));

((ipaddr.sin_port=htons((u_)atoi(service)))0)
{
prf(\"get portnumber error\\n\");
[Page] WSACleanup;
INVALID_SOCKET;
}


//从传输协议得到对应编号
((protoin=getprotobyname(transport))0)
{
prf(\"get protocol number error\\n\");
WSACleanup;
INVALID_SOCKET;
}
//根据传输协议给对应变量赋值
(strcmp(transport,\"udp\")0)
type=SOCK_DGRAM;

type=SOCK_STREAM;
//创建套接字
sock=(PF_INET,type,protoin->p_proto);
(sockINVALID_SOCKET)
{
prf(\"creat error\\n\");
WSACleanup;
INVALID_SOCKET;
[Page] }
//绑定本地IP
(bind(sock,(struct sockaddr*)&ipaddr,(ipaddr))SOCKET_ERROR)
{
prf(\" bind error\\n\");
WSACleanup;
SOCKET_ERROR;
}
//如果是流式传输(TCP)使套接字处于监听状态等待来自客户机连接参数qlen的指定等待
//队列长度
(typeSOCK_STREAM)


{
(listen(sock,qlen)SOCKET_ERROR)
{
prf(\" listen errror\\n\");
WSACleanup;
SOCKET_ERROR;
}
}
sock;
[Page]}


//************************************
//UDPServer
//************************************
SOCKET UDPServer(const char *service)
{
SocketServer(service,\"udp\",0);
}

//************************************
//TCPServer
//************************************
SOCKET TCPServer(const char *service, qlen)
{
SocketServer(service,\"tcp\",qlen);
}

4服务器例子(TCP):
//接受客户端连接每接收到客户端发送而来数据则打印在控制台
#<winsock.h>
#<.h>
#<stdio.h>
#<stdlib.h>
#\"SocketServer.h\"
#pragma comment(lib,\"wsock32\")

# QLEN 5
# BUFSIZE 5
# WAVERS MAKEWORD(2,0)//WORD MAKEWORD( bLow, bHigh);

SOCKET TCPServer(const char*service, qlen);
void ( argc,char*argv)
{
char *service=\"3333\";//默认端口号
struct sockaddr_in fsin;
SOCKET msock,ssock;
WSADATA wsadata;
alen,cc;
char buf[BUFSIZE];

switch(argc)
{
1:


;//采用默认端口号
2:
service=argv[1];//采用命令行端口号
;
default:
prf(\"argment error\\n\");
exit(1);
}
(WSAStartup(WAVERS,&wsadata)!=0)//化Winsock
{
prf(\"initalize failed\\n\");
WSACleanup;//清除Winsock
exit(1);
}
[Page]
msock=TCPServer(service,QLEN);//采用TCP协议

while(1)
{
alen=(struct sockaddr);
ssock=accept(msock,(struct sockaddr*)&fsin,&alen);//accept阻塞接收客户端请求

(ssockINVALID_SOCKET)
{
prf(\"initialize failed\\n\");
WSACleanup;
exit(1);
}
while(cc=recv(ssock,buf,(buf)-1,0))//接收客户端信息当收到信息为零时则退出
{
buf[cc]=\'\\0\';
prf(\"%s\",buf);
}
prf(\"connect close...\");
close(ssock);
;
}
}



以上是两个完整客户端和服务端可建立两个VC控制台工程编译运行进行连接测试
Tags:  如何编写程序 怎么编写程序 编写程序 程序编写学习

延伸阅读

最新评论

发表评论