利用Socket实现文本文件传输

Dmeilin830 2010-04-20 03:29:04
简单介绍一下:
服务器端使用ServerSocket并打开个端口等待客户端的联结,客户端使用Socket定位服务器端口。 然后客户端打开文本文件并发送至服务器: ,。我需要知道的是,服务器端循环监听的部分程序怎么写,如果需要的话,我可以把,客户端发送的程序写下来,是论坛上下载的一个程序的部分。我看了下,觉得没有改的必要。
另外,文件成功接收后,读取其中的数据(里面放的都是十进制的数据)。怎么做。。谢谢了。
UINT SendFile(void *p/*窗口指针*/)
{


CString strError;
ASSERT(p!=NULL);//
CCLientDlg *pDlg = (CCLientDlg*)p;
CString strIP;
pDlg->m_cSvrIP.GetWindowText(strIP);//得到输入的IP地址。
sockaddr_in addr;//sockaddr_in为地址结构体变量
addr.sin_family=AF_INET;//表示在INT上通信
addr.sin_addr.S_un.S_addr=inet_addr(strIP.GetBuffer(0));
addr.sin_port=htons(pDlg->m_iPort);
int ret=0;
int error=0;
ret=connect(pDlg->m_hSocket,(LPSOCKADDR)&addr,sizeof(addr));//主动连接服务器
if(ret==SOCKET_ERROR)
{
strError.Format("Connect Error:%d ",error=WSAGetLastError());
AfxMessageBox(strError);
closesocket(pDlg->m_hSocket);
return -1;
}

//文件操作

CString strPathName = pDlg->m_strPathName;
CFile file;
if(!file.Open(strPathName, CFile::modeRead | CFile::typeBinary))
{
AfxMessageBox("打开文件失败");
return -1;
}
long lFileSize = file.GetLength();
pDlg->m_progress.ShowWindow(SW_SHOW);
pDlg->m_progress.SetRange32(0, lFileSize); //设置进度条范围
pDlg->m_progress.SetStep(1); //设置进度条步长
char temp[1024]; //首先用来存放文件大小,后面用作发送文件缓冲区
memset(temp,0,sizeof(temp));
ltoa(lFileSize, temp, 10); //转化为字符
CString str;
str = pDlg->m_strFileName;
str += "*";
str += temp;
int i=str.GetLength();
int ret1=send(pDlg->m_hSocket, str, str.GetLength(), 0); //发送文件的名称和大小
if (ret1==SOCKET_ERROR)
{
strError.Format("Send File:%d",error=WSAGetLastError());
AfxMessageBox(strError);
return -1;
}

/////////////////////////发送文件///////////////////////////////////////////
int iEnd =0;
int ilen =0;
long iTmp =0;
while (1)
{
ilen = file.Read(temp, 1024);
if (ilen==0)
{
break;
}
iEnd = send(pDlg->m_hSocket,temp,ilen,0);
if (iEnd==SOCKET_ERROR)
{
strError.Format("Send File:%d",error=WSAGetLastError());
AfxMessageBox(strError);
break;
}
iTmp +=iEnd;
pDlg->m_progress.SetPos(iTmp);

}
file.Close();
/////////////////判断发送是否成功、结束处理////////////////////////////////////
closesocket(pDlg->m_hSocket);
if (iTmp == lFileSize)
{
//AfxMessageBox("文件发送成功!");

}
else
{
strError.Format("文件发送失败");
AfxMessageBox(strError);
return 0;
}
CString strTemp="发送文件结束";
pDlg->m_cState.SetWindowText(strTemp);
//shutdown();
ExitThread(0);
return 0;
}
...全文
502 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Dmeilin830 2010-04-21
  • 打赏
  • 举报
回复
非常感谢,对我有很大的启发。
[Quote=引用 7 楼 yincheng01 的回复:]
server端开个线程监听,等待client来connect

C/C++ code
//
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if ( m_socket == INVALID_SOCKET )
{
AfxMessageBox(L"create socket : failed !");
return FALSE;
……
[/Quote]
Dmeilin830 2010-04-21
  • 打赏
  • 举报
回复
多谢,有点明白了。我再试试。
我需要问到东西还挺多。把文件接收下来,还要对txt文件的内容操作。最好把数据用曲线的形式表现出来,磨练,有好的代码先拿来借用,等弄得差不多再探究一二
[Quote=引用 6 楼 zxdyu2009 的回复:]
C/C++ code

//
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if ( m_socket == INVALID_SOCKET )
{
AfxMessageBox(L"create socket : failed !");
return FALSE;
……
[/Quote]
Sou2012 2010-04-21
  • 打赏
  • 举报
回复
祝楼主成功!
尹成 2010-04-20
  • 打赏
  • 举报
回复
server端开个线程监听,等待client来connect

C/C++ code
//
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if ( m_socket == INVALID_SOCKET )
{
AfxMessageBox(L"create socket : failed !");
return FALSE;
}

// 将套接字绑扎到用户指定端口及默认的接口
m_stSrcAddr.sin_family = AF_INET;
m_stSrcAddr.sin_port = htons (m_iSvrPort);//你定义m_iSvrPort的值 如6000
m_stSrcAddr.sin_addr.s_addr =htonl(INADDR_ANY); //inet_addr(m_strLocalAddr);
int nRet = bind (m_socket, (struct sockaddr FAR *)&m_stSrcAddr, sizeof(struct sockaddr));
if ( nRet == SOCKET_ERROR )
{
AfxMessageBox(L"bind : failed !");
return FALSE;
}

if ( SOCKET_ERROR == listen(m_socket,10) )
{
AfxMessageBox(L"Listen : failed !");
return FALSE;
}
::AfxBeginThread(g_AcceptSvrThread,(LPVOID)&m_socket);

//
//
UINT g_AcceptSvrThread(LPVOID lparam)
{
SOCKET s = *((SOCKET*)lparam);
while ( 1 )
{
DWORD dwCount = ::GetTickCount();
SOCKET acceptSock;
SOCKADDR_IN addr;
int iLen = sizeof(SOCKADDR_IN);
acceptSock = accept(s, (SOCKADDR*)&addr, &iLen);
if (INVALID_SOCKET == acceptSock)
{
closesocket(acceptSock);
return -1;
}
::AfxBeginThread(g_FileSvrThread,&acceptSock);
dwCount = ::GetTickCount() - dwCount ;
if ( dwCount > 1000 )//这里写的1000ms,看你的情况了
{
continue;
}
else
{
Sleep(1000-dwCount);
}
}
return 0;
}
//
UINT g_FileSvrThread(LPVOID lparam)
{
// AfxMessageBox(L"g_FileSvrThread begin!");
CString str = L"";
SOCKET Sock = *((SOCKET*)lparam);
CString strMsg = L"";
bool bConnected = true;
while ( 1 )
{
DWORD dwCount = GetTickCount();
int iRet = 0;
//这里写recv代码
// CMD cmd;
// memset(&cmd, 0 ,sizeof(cmd));
// iRet = recv(Sock, (char*)&cmd, sizeof(cmd), 0);
// if ( iRet <= 0 )
// {
// bConnected = false;
// }

//recv完后,可以用内存中的数据写入文件了。
//file write ,hehe
//TRACE("接收过程结束,要接受的大小%d,剩余大小%d\n", iSize, iLeft);
if ( !bConnected )
break;
}
closesocket(Sock);
return 0;
}


以上代码很简单,阻塞式的,服务端开一线程用来accept 客户端,每accept一个,开一个线程,用来与这处客户端发送文件,而accept线程还是在工作,继续等待新的客户端到来。在文件发送线程中要处理客户端退出时,线程退出的代码。比如通过客户端发送来的信息,判断,或者客户异常退出时,阻塞recv会返回0或者负值,具体看看客户端异常断电等情况下recv会返回什么,来退出线程,以免线程浪费资源。

以上代码是unicode形式的,如果你不是,把里面的字符串前面的L去年。
zxdyu2009 2010-04-20
  • 打赏
  • 举报
回复

//
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if ( m_socket == INVALID_SOCKET )
{
AfxMessageBox(L"create socket : failed !");
return FALSE;
}

// 将套接字绑扎到用户指定端口及默认的接口
m_stSrcAddr.sin_family = AF_INET;
m_stSrcAddr.sin_port = htons (m_iSvrPort);//你定义m_iSvrPort的值 如6000
m_stSrcAddr.sin_addr.s_addr =htonl(INADDR_ANY); //inet_addr(m_strLocalAddr);
int nRet = bind (m_socket, (struct sockaddr FAR *)&m_stSrcAddr, sizeof(struct sockaddr));
if ( nRet == SOCKET_ERROR )
{
AfxMessageBox(L"bind : failed !");
return FALSE;
}

if ( SOCKET_ERROR == listen(m_socket,10) )
{
AfxMessageBox(L"Listen : failed !");
return FALSE;
}
::AfxBeginThread(g_AcceptSvrThread,(LPVOID)&m_socket);

//
//
UINT g_AcceptSvrThread(LPVOID lparam)
{
SOCKET s = *((SOCKET*)lparam);
while ( 1 )
{
DWORD dwCount = ::GetTickCount();
SOCKET acceptSock;
SOCKADDR_IN addr;
int iLen = sizeof(SOCKADDR_IN);
acceptSock = accept(s, (SOCKADDR*)&addr, &iLen);
if (INVALID_SOCKET == acceptSock)
{
closesocket(acceptSock);
return -1;
}
::AfxBeginThread(g_FileSvrThread,&acceptSock);
dwCount = ::GetTickCount() - dwCount ;
if ( dwCount > 1000 )//这里写的1000ms,看你的情况了
{
continue;
}
else
{
Sleep(1000-dwCount);
}
}
return 0;
}
//
UINT g_FileSvrThread(LPVOID lparam)
{
// AfxMessageBox(L"g_FileSvrThread begin!");
CString str = L"";
SOCKET Sock = *((SOCKET*)lparam);
CString strMsg = L"";
bool bConnected = true;
while ( 1 )
{
DWORD dwCount = GetTickCount();
int iRet = 0;
//这里写recv代码
// CMD cmd;
// memset(&cmd, 0 ,sizeof(cmd));
// iRet = recv(Sock, (char*)&cmd, sizeof(cmd), 0);
// if ( iRet <= 0 )
// {
// bConnected = false;
// }

//recv完后,可以用内存中的数据写入文件了。
//file write ,hehe
//TRACE("接收过程结束,要接受的大小%d,剩余大小%d\n", iSize, iLeft);
if ( !bConnected )
break;
}
closesocket(Sock);
return 0;
}

以上代码很简单,阻塞式的,服务端开一线程用来accept 客户端,每accept一个,开一个线程,用来与这处客户端发送文件,而accept线程还是在工作,继续等待新的客户端到来。在文件发送线程中要处理客户端退出时,线程退出的代码。比如通过客户端发送来的信息,判断,或者客户异常退出时,阻塞recv会返回0或者负值,具体看看客户端异常断电等情况下recv会返回什么,来退出线程,以免线程浪费资源。

以上代码是unicode形式的,如果你不是,把里面的字符串前面的L去年。
bragi523 2010-04-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dmeilin830 的回复:]
说的有点笼统了啊。我还有个问题,怎么读取文本数据?
我只知道怎样写入:
my_file1.Open(pFileName1,CFile::modeCreate|CFile::modeWrite);

my_file1.Write(m_cstring_volut,m_cstring_volut.GetLength());
my_file1.Close();

引用 1 楼 ilysony……
[/Quote]Ctrl +F 把所有Write改成Read就行了
Dmeilin830 2010-04-20
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 visualeleven 的回复:]
这种东西,网上一搜一大把的,简单一点server端开个线程监听,等待client来connect
[/Quote]额的神,唉
Eleven 2010-04-20
  • 打赏
  • 举报
回复
这种东西,网上一搜一大把的,简单一点server端开个线程监听,等待client来connect
Dmeilin830 2010-04-20
  • 打赏
  • 举报
回复
说的有点笼统了啊。我还有个问题,怎么读取文本数据?
我只知道怎样写入:
my_file1.Open(pFileName1,CFile::modeCreate|CFile::modeWrite);

my_file1.Write(m_cstring_volut,m_cstring_volut.GetLength());
my_file1.Close();
[Quote=引用 1 楼 ilysony 的回复:]
服务器端循环监听的部分程序怎么写

最简单的就是 while (TRUE) { }

在Windows 上用 select 或完成端口。

linux下有epoll
[/Quote]
Sou2012 2010-04-20
  • 打赏
  • 举报
回复
服务器端循环监听的部分程序怎么写

最简单的就是 while (TRUE) { }

在Windows 上用 select 或完成端口。

linux下有epoll
目 录 一、目录…………………………………………………………………1 二、题目……………………………………………………………2 三、设计任务…………………………………………………2 四、WinSocket简介及特点原理…………………………………2 五、TCP简介及特点原理………………………………………3 六、Visual C++简介………………………………………………7 七、设计方案…………………………………………………8 八、系统的原理框图和程序流程图………………………10 九、实验中的问题…………………………………………………14 十、实验结果及分析………………………………………………14 十一、课程设计的总结体会………………………………………16 十二、参考文献……………………………………………………16 利用Socket实现双机通信 一、设计任务 1.利用WinSock来实现双机通信,理解TCP状态机图。 2.要求使用WinSock编程,采用其中的TCP面向连接方式,实现文本数据的交换。 二、WinSocket简介及特点原理 2.1、什么是socket 所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应 用程序通常通过"套接字"向网络发出请求或者应答网络请求。 Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用 它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解So cket接口。 Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和 输出的话,就很容易了解Socket了。网络的Socket数据传输是一种特殊的I/O,Socket也 是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返 回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现 的。 常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_D GRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Soc ket是一种无连接的Socket,对应于无连接的UDP服务应用。   最重要的是,socket 是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的socket 系统调用。客户随机申请一个socket (相当于一个想打电话的人可以在任何一台入网电话上拨号呼叫),系统为之分配一个so cket号;服务器拥有全局公认的 socket ,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫 方知道的电话号码)。 socket利用客户/服务器模式巧妙地解决了进程之间建立通信连接的问题。服务器so cket 半相关为全局所公认非常重要。不妨考虑一下,两个完全随机的用户进程之间如何建立 通信?假如通信双方没有任何一方的socket 固定,就好比打电话的双方彼此不知道对方的电话号码,要通话是不可能的。 2.2、WinSocket的通信原理 WinSock是一个基于Socket模型的 API。WinSock在 Windows98,Window NT中使用。WinSock一般由两部分组成:开发组件和运行组件。开发组件是供程序员在w indows环境下开发网络应用程序使用的,它包括应用程序接口库函数、头文件和实现的 文档,其中最主要的是WINSOCK.H运行组件是以动态链接库(DlL)来实现socket接口的。 文件名为WINSOCK.DLL应用程序在执行时装入它就能实现网络通信功能 三、TCP简介及特点原理 1.什么是TCP TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能 。   在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常 需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包 交换。   应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分 割成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传送单元(MTU )的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层 。TCP为了保证不发生丢包,就给每个字节一个序号,同时序号也保证了传送到接收端实 体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧