UNIX下的C函数移植到Windows2000下,谢谢帮助!
http://community.csdn.net/Expert/topic/3700/3700725.xml?temp=.8901026
以下是两个UNIX下的c函数,分别实现发送及接收文件,参数sock为端口号,我不知道这段函数在Windows2000系统下能不能直接用?如果不能,该怎么做才能改成widnows下能用的?请大侠帮忙,先谢谢大家了!!问题解决后,再送上100分。
//文件接收函数
int IBrcvfile(int sock,char *rcvfile)
{
int r,len,last=0;
char info[2],slen[5];
#ifndef MAXSTRINGLEN
#define MAXSTRINGLEN 128
#endif
#ifndef INFO_NORMAL
#define INFO_NORMAL "N"
#endif
#ifndef INFO_END
#define INFO_END "E"
#endif
#ifndef INFO_RESP
#define INFO_RESP "R"
#endif
char str[MAXSTRINGLEN],cmd[128];
FILE *fp;
memset(str,0,MAXSTRINGLEN);
fp=fopen(rcvfile,"w+");
if(fp==NULL)
{
return -1;
}
while(1)
{
memset(str, 0, MAXSTRINGLEN);
memset(slen, 0, sizeof(slen));
//IBcomlog_print(__FILE__,__LINE__,"read info");
r=read(sock,info,1);
if(r<0)
{
fclose(fp);
return -2;
}
//IBcomlog_print(__FILE__,__LINE__,"read info[%s]",info);
if(strncmp(info,INFO_END,1)!=0&&strncmp(info,INFO_NORMAL,1)!=0)
{
fclose(fp);
return -3;
}
if(!strncmp(info,INFO_END,1))
last=1;
r=read(sock,slen,4);
//IBcomlog_print(__FILE__,__LINE__,"read slen=[%s]",slen);
if(r!=4)
{
fclose(fp);
return -4;
}
len=atoi(slen);
r=read(sock,str,len);
//IBcomlog_print(__FILE__,__LINE__,"read buf[%s] r=%d",str,r);
if(r!=len)
{
fclose(fp);
return -5;
}
//IBcomlog_print(__FILE__,__LINE__,"write resp");
r=write(sock,INFO_RESP,1);
if(r!=1)
{
fclose(fp);
return -6;
}
//IBcomlog_print(__FILE__,__LINE__,"write resp");
r=fwrite(str,len,1,fp);
if(r<0)
{
fclose(fp);
return -7;
}
if(last)
break;
}
fclose(fp);
return 0;
}
//文件发送函数
int IBsndfile(int sock,char *sndfile)
{
int r,len,last=0;
char info[2],slen[5];
#ifndef MAXSTRINGLEN
#define MAXSTRINGLEN 128
#endif
#ifndef INFO_NORMAL
#define INFO_NORMAL "N"
#endif
#ifndef INFO_END
#define INFO_END "E"
#endif
#ifndef INFO_RESP
#define INFO_RESP "R"
#endif
char str[MAXSTRINGLEN],cmd[128];
FILE *fp;
memset(str,0,MAXSTRINGLEN);
fp=fopen(sndfile,"r");
if(fp==NULL)
{
return -1;
}
while(1)
{
memset(str, 0, MAXSTRINGLEN);
memset(slen, 0, sizeof(slen));
//IBcomlog_print(__FILE__,__LINE__,"fread ");
r=fread(str,MAXSTRINGLEN,1,fp);
if(r<0)
{
fclose(fp);
return -6;
}
len=strlen(str);
if(len<MAXSTRINGLEN||feof(fp))
last=1;
//IBcomlog_print(__FILE__,__LINE__,"write info ");
if(last)
{
r=write(sock,INFO_END,1);
//IBcomlog_print(__FILE__,__LINE__,"write info end");
}
else
{
r=write(sock,INFO_NORMAL,1);
//IBcomlog_print(__FILE__,__LINE__,"write info normal");
}
if(r!=1)
{
fclose(fp);
return -2;
}
sprintf(slen,"%4d",len);
r=write(sock,slen,4);
//IBcomlog_print(__FILE__,__LINE__,"write slen [%s] r=%d",slen,r);
if(r!=4)
{
fclose(fp);
return -4;
}
//IBcomlog_print(__FILE__,__LINE__,"write buf[%s] ",str);
r=write(sock,str,len);
if(len!=r)
{
fclose(fp);
return -5;
}
r=read(sock,info,1);
//IBcomlog_print(__FILE__,__LINE__,"read resp [%c] r=%d",info[0],r);
if(r!=1)
{
fclose(fp);
return -6;
}
if(strncmp(info,INFO_RESP,1))
{
fclose(fp);
return -7;
}
if(last)
break;
}
fclose(fp);
return 0;
}
问题点数:100、回复次数:14Top
1 楼tb01412(tb)回复于 2005-01-05 15:56:44 得分 0
在WINDOWS下看你用什么开发平台实现了,如果用VB,用控件就可以,并且发送和接收很简单的。
如果是用VC,则有N种实现方式,比较简单的就是用MFC。如果你用这两种方式开发的话,我这儿有源码,QQ号:382270255Top
2 楼zzllabc(抱朴子--清心释累,绝率忘情)回复于 2005-01-05 16:07:25 得分 0
我用VC,目的:采用上面两个函数实现文件传送,不用MFC等,请多指教!Top
3 楼tb01412(tb)回复于 2005-01-05 16:14:16 得分 30
你不用MFC,你在VC下用纯API编程吗?
下面我是在一篇文章中截取的一段关于用API进行WINSOCK通信的例子:
为了简单起见,服务器端和客户端的应用程序均是基于MFC的标准对话框,网络通信部分基于Winsock2 API实现。
先做服务器端应用程序。
用MFC向导做一个基于对话框的应用程序SocketSever,注意第三步中不要选上Windwos Sockets选项。在做好工程后,创建一个SeverSock,将它设置为异步非阻塞模式,并为它注册各种网络异步事件,然后与自定义的网络异步事件联系上,最后还要将它设置为监听模式。在自定义的网络异步事件的回调函数中,你可以得到各种网络异步事件,根据它们的类型,做不同的处理。下面将详细介绍如何编写相关代码。
在SocketSeverDlg.h文件的类定义之前增加如下定义:
#define NETWORK_EVENT WM_USER+166 file://定义网络事件
SOCKET ServerSock; file://服务器端Socket
在类定义中增加如下定义:
class CSocketSeverDlg : CDialog
{
…
public:
SOCKET ClientSock[CLNT_MAX_NUM]; file://存储与客户端通信的Socket的数组
/*各种网络异步事件的处理函数*/
void OnClose(SOCKET CurSock); file://对端Socket断开
void OnSend(SOCKET CurSock); file://发送网络数据包
void OnReceive(SOCKET CurSock); file://网络数据包到达
void OnAccept(SOCKET CurSock); file://客户端连接请求
BOOL InitNetwork(); file://初始化网络函数
void OnNetEvent(WPARAM wParam, LPARAM lParam); file://异步事件回调函数
…
};
在SocketSeverDlg.cpp文件中增加消息映射,其中OnNetEvent是异步事件回调函数名:
ON_MESSAGE(NETWORK_EVENT,OnNetEvent)
定义初始化网络函数,在SocketSeverDlg.cpp文件的OnInitDialog()中调此函数即可。
BOOL CSocketSeverDlg::InitNetwork()
{
WSADATA wsaData;
file://初始化TCP协议
BOOL ret = WSAStartup(MAKEWORD(2,2), &wsaData);
if(ret != 0)
{
MessageBox("初始化网络协议失败!");
return FALSE;
}
file://创建服务器端套接字
ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ServerSock == INVALID_SOCKET)
{
MessageBox("创建套接字失败!");
closesocket(ServerSock);
WSACleanup();
return FALSE;
}
file://绑定到本地一个端口上
sockaddr_in localaddr;
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(8888); file://端口号不要与其他应用程序冲突
localaddr.sin_addr.s_addr = 0;
if(bind(ServerSock ,(struct sockaddr*)&localaddr,sizeof(sockaddr))
= = SOCKET_ERROR)
{
MessageBox("绑定地址失败!");
closesocket(ServerSock);
WSACleanup();
return FALSE;
}
file://将SeverSock设置为异步非阻塞模式,并为它注册各种网络异步事件,其 中 m_hWnd
file://为应用程序的主对话框或主窗口的句柄
if(WSAAsyncSelect(ServerSock, m_hWnd, NETWORK_EVENT,
FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR)
{
MessageBox("注册网络异步事件失败!");
WSACleanup();
return FALSE;
}
listen(ServerSock, 5); file://设置侦听模式
return TRUE;
}
下面定义网络异步事件的回调函数
void CSocketSeverDlg::OnNetEvent(WPARAM wParam, LPARAM lParam)
{
file://调用Winsock API函数,得到网络事件类型
int iEvent = WSAGETSELECTEVENT(lParam);
file://调用Winsock API函数,得到发生此事件的客户端套接字
SOCKET CurSock= (SOCKET)wParam;
switch(iEvent)
{
case FD_ACCEPT: file://客户端连接请求事件
OnAccept(CurSock);
break;
case FD_CLOSE: file://客户端断开事件:
OnClose(CurSock);
break;
case FD_READ: file://网络数据包到达事件
OnReceive(CurSock);
break;
case FD_WRITE: file://发送网络数据事件
OnSend(CurSock);
break;
default: break;
}
}
以下是发生在相应Socket上的各种网络异步事件的处理函数,其中OnAccept传进来的参数是服务器端创建的套接字,OnClose()、OnReceive()和OnSend()传进来的参数均是服务器端在接受客户端连接时新创建的用与此客户端通信的Socket。
void CSocketSeverDlg::OnAccept(SOCKET CurSock)
{
file://接受连接请求,并保存与发起连接请求的客户端进行通信Socket
file://为新的socket注册异步事件,注意没有Accept事件
}
void CSocketSeverDlg::OnClose(SOCET CurSock)
{
file://结束与相应的客户端的通信,释放相应资源
}
void CSocketSeverDlg::OnSend(SOCET CurSock)
{
file://在给客户端发数据时做相关预处理
}
void CSocketSeverDlg::OnReceive(SOCET CurSock)
{
file://读出网络缓冲区中的数据包
}
用同样的方法建立一个客户端应用程序。初始化网络部分,不需要将套接字设置为监听模式。注册异步事件时,没有FD_ACCEPT,但增加了FD_CONNECT事件,因此没有OnAccept()函数,但增加了OnConnect()函数。向服务器发出连接请求时,使用connect()函数,连接成功后,会响应到OnConnect()函数中。下面是OnConnect()函数的定义,传进来的参数是客户端Socket和服务器端发回来的连接是否成功的标志。
void CSocketClntDlg::OnConnect(SOCKET CurSock, int error)
{
if(0 = = error)
{
if(CurSock = = ClntSock)
MessageBox("连接服务器成功!");
}
}
定义OnReceive()函数,处理网络数据到达事件;
定义OnSend()函数,处理发送网络数据事件;
定义OnClose()函数,处理服务器的关闭事件。
Top
4 楼zzllabc(抱朴子--清心释累,绝率忘情)回复于 2005-01-05 16:20:53 得分 0
谢谢,不过跟我的要求有点距离,我再看看。Top
5 楼spiderww(spider)回复于 2005-01-05 16:21:02 得分 10
恩,有个现成的程序看着总是快一点Top
6 楼zzllabc(抱朴子--清心释累,绝率忘情)回复于 2005-01-05 16:33:00 得分 0
多谢各位的热心帮助,我感觉还是跟我的要求有一定距离,还是非常感谢!Top
7 楼tb01412(tb)回复于 2005-01-05 16:40:04 得分 30
兄弟,在WINDOWS下开发WINSOCK程序首先需要作一些库的初始化库之类的工作,就像是在LINUX下初始化套接字一样,我知道你的意思,你是想作一个通用的(无论是在WINDOWS还是LINUX)下可移植的收发文件的函数,这样的话,你有两种方式:
其一:用JAVA写,不需要任何改动
其二:用大量的#IFDEF之类的语句来初始化套接字,然后用跨平台的读写文件的函数Top
8 楼jimsuker(Fish)回复于 2005-01-05 18:15:04 得分 20
read 改为recv
write 改为send
要给我加分,还要请我吃饭Top
9 楼jimsuker(Fish)回复于 2005-01-05 18:16:59 得分 0
windows ,unix 下通用
:-)Top
10 楼freeheart1977(逍遥的心)回复于 2005-01-05 23:57:44 得分 10
可用Top
11 楼zzllabc(抱朴子--清心释累,绝率忘情)回复于 2005-01-06 08:08:32 得分 0
再顶起来!Top
12 楼spiderww(spider)回复于 2005-01-06 09:35:59 得分 0
个人感觉jimsuker(Fish)是个mm,不知道对不对.Top
13 楼zzllabc(抱朴子--清心释累,绝率忘情)回复于 2005-01-06 09:58:26 得分 0
再顶,不管是不是MM,只要帮我解决问题,我就请吃饭^_^Top
14 楼jimsuker(Fish)回复于 2005-01-06 15:25:26 得分 0
加分,老大Top




