新手求助,请问SOCKET怎么传输图片?
假如我有一张图片a.jpg在C:\,请问我该怎么传输它呢? 关键是对方接收完数据流过后该怎么把一堆数据还原成一张图片显示出来?
[解决办法]
其实,传输图片就是传图片
详细可以见下
借用一个网友的代码
/******************************************************** FilePoster关键代码*E-mail: andy.zhshg@163.com*日期: 2008.12.25**程序描述:*FilePoster是基于Win32平台的网络文件传输程序。开发平台为*Visual C++6.0。*程序采用服务器/客户机模式,服务器用于接收数据,客户机负责发送数据。利用windows多线程原理,集接收和发送功能于一体。*网络传输采用UDP原理,为解决UDP传输的不可靠性,用Windows*消息对收发的双方进行同步,即发送方先发送消息请求传送文件*同时发送要传文件的基本信息,收取方收到后回复发送发一个确*认消息,然后发送方依次发送被分成固定大小块(256字节)的文*件数据,收取方每收到一个数据块就写入自己的文件并回复发送*方一个接收完毕消息,以使得发送方发送下一个数据块。发送方*发送最后一个数据块时添加发送结束标记,接受方接收完毕后关*闭文件,至此发送过程结束。**问题阐述:*程序的缺陷在于只能用于具有固定IP的主机之间的文件传输。在*处于不同的内网中的主机无能为力。因为对于内网中的计算机其*IP是主机通过映射后分配来的所以如果不借助于服务器很难从外*网访问内网的计算机。不过对于处于同一局域网的计算机,本程*序还是能够完全应付的。*限于篇幅,与文件传输无关的代码省略,以"......"代替。*********************************************************//**********************************************************程序的初始化函数*********************************************************/BOOL CFilePosterApp::InitInstance(){ //加载套接字库 if(!AfxSocketInit()) { AfxMessageBox("加载套接字库失败!"); return FALSE; } ......}/***********************************************************主窗口的初始化函数*struct RECVPARAM 用于传递线程数据**********************************************************/struct RECVPARAM{ HWND hWnd; SOCKET sock;};BOOL CFilePosterDlg::OnInitDialog(){ ...... //设定进度条的步进值 m_progress.SetStep(1); m_progress_r.SetStep(1); //创建套接字 m_socket=socket(AF_INET,SOCK_DGRAM,0); if(INVALID_SOCKET==m_socket) { MessageBox("套接字创建失败!"); return FALSE; } SOCKADDR_IN addrSock; addrSock.sin_family=AF_INET; addrSock.sin_port=htons(6800); addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY); //绑定套接字 int retval; retval=bind(m_socket, (SOCKADDR*)&addrSock, sizeof(SOCKADDR)); if(SOCKET_ERROR==retval) { closesocket(m_socket); MessageBox("绑定失败!"); return FALSE; } //产生一个用于接收数据的线程 struct RECVPARAM *pRecvParam=new RECVPARAM; pRecvParam->sock=m_socket; pRecvParam->hWnd=m_hWnd; HANDLE hThread=CreateThread(NULL, 0, RecvProc, (LPVOID)pRecvParam, 0, NULL); CloseHandle(hThread); ......}/***************************************************************接收线程的回调函数*发送的数据块结构解析:*类别 字节号 内容*H 1 通信头,申请发送*H 2~257 文件名*H 258~... 文件大小*D 1 通信头,拒绝接收*R 1 通信头,同意接收*F 1 通信头,发送文件块*F 2~17 保留*F 18~... 文件数据块*E 1 通信头,文件尾发送*E 2~17 块大小*E 18~... 文件数据块**************************************************************/DWORD WINAPI CFilePosterDlg::RecvProc(LPVOID lpParameter){ SOCKET sock=((RECVPARAM*)lpParameter)->sock; HWND hWnd=((RECVPARAM*)lpParameter)->hWnd; delete lpParameter; SOCKADDR_IN addrFrom; int len=sizeof(SOCKADDR); char recvBuf[0x112]; //256+17字节的接受缓冲数组 char fileName[0x100]; //256字节的文件名存储区 int retval, i; FILE* file = NULL; while(TRUE) { //接受UDP数据 retval=recvfrom(sock, recvBuf, 0x112, 0, (SOCKADDR*)&addrFrom, &len); if(SOCKET_ERROR == retval) break; //收到消息头为'R',即对方同意让你继续发送数据 if (recvBuf[0] == 'R') { char wParam = 'R'; ::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, 0); } //收到消息头为'D',即对方拒绝让你继续发送数据 else if (recvBuf[0] == 'D') { char wParam = 'D'; ::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, 0); } //收到消息头为'H',即对方申请给你发送信息,并送来文件的信息 else if (recvBuf[0] == 'H') { //从收到的数据中提取文件名信息 for (i = 1; i <= 0x100 && recvBuf[i] != '/0'; i++) fileName[i-1] = recvBuf[i]; fileName[i-1] = '/0'; //从收到的数据中提取文件大小信息 CString recvMsg; nFileSize = atoi(&recvBuf[0x101]); recvMsg.Format("收到来自于(%s)的文件:%s/n文件大小:%i字节/n是否接收?", inet_ntoa(addrFrom.sin_addr), fileName, nFileSize); //用消息框提示用户有人要发送文件 if (IDOK == AfxMessageBox(recvMsg, MB_OKCANCEL)) { //若用户同意接收,提供一个文件保存对话框用于设定保存的路径 CFileDialog saveDlg(false, NULL, fileName); if (IDOK == saveDlg.DoModal()) { //创建一个文件用于复制接收的文件数据 if (!(file = fopen(saveDlg.GetPathName(), "wb"))) { AfxMessageBox("创建本地文件失败!"); continue; } char wParam = 'H'; ::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom); } else { char wParam = 'C'; ::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom); } } else //用户拒绝接收 { char wParam = 'C'; ::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom); } } //收到的消息头为'F',即对方发来的是文件数据 else if (recvBuf[0] == 'F') { //将文件数据写入本地文件中 fwrite(&recvBuf[0x12], 1, 0x100, file); char wParam = 'F'; ::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom); } //收到的消息头为'E',即对方发来最后一个数据块 else if (recvBuf[0] == 'E') { //获取数据块的大小 int bufSize = atoi(&recvBuf[1]); //将数据块写入本地文件,并关闭文件 fwrite(&recvBuf[0x12], 1, bufSize, file); fclose(file); char wParam = 'E'; ::PostMessage(hWnd, WM_READY_TO_RECEIVE, (WPARAM)&wParam, (LPARAM)&addrFrom); } //收到未定义的数据头 else AfxMessageBox("传送数据过程中出现错误!"); } return (DWORD)NULL;}/**************************************************************按下发送键,发出文件信息的函数*************************************************************/void CFilePosterDlg::OnOK() { if (m_posting) //bool m_posting 表示程序是否正在发送文件 { MessageBox("数据发送中,请稍候再试。"); return; } UpdateData(); if (m_filePath == "") { MessageBox("请输入要发送的文件路径!"); return; } if (m_IPAddr.IsBlank()) { MessageBox("请添入接收者的IP地址。"); return; } WIN32_FIND_DATA FindFileData; if (INVALID_HANDLE_VALUE == FindFirstFile(m_filePath, &FindFileData)) { MessageBox("文件路径错误或文件不存在!/n请重新指定文件路径。"); return; } DWORD dwIP; m_IPAddr.GetAddress(dwIP); SOCKADDR_IN addrTo; addrTo.sin_family=AF_INET; addrTo.sin_port=htons(6800); addrTo.sin_addr.S_un.S_addr=htonl(dwIP); //构建文件信息数据块 char sendBuf[0x112]; int i; //消息头 sendBuf[0] = 'H'; //文件名 for (i = 1; i <= 0x100 && FindFileData.cFileName[i-1] != '/0'; i++) sendBuf[i] = FindFileData.cFileName[i-1]; sendBuf[i] = '/0'; //文件大小 _itoa(FindFileData.nFileSizeLow, &sendBuf[0x101], 10); sendBuf[0x111] = '/0'; //发送数据块 sendto(m_socket, sendBuf, 0x112, 0, (SOCKADDR*)&addrTo, sizeof(SOCKADDR)); //打开文件,等待读取 if (!(m_file = fopen(m_filePath, "rb"))) { MessageBox("读取文件失败!"); } m_nSend = 0; //已发送的块数 m_nFileSize_s = FindFileData.nFileSizeLow; //文件大小 m_progress.SetRange(0, m_nFileSize_s/0x100+1);//设置发送进度条 m_posting = true; //标明发送正进行 }