C++利用SOCKET传送文件

合集下载

c#中Socket进行文件传输

c#中Socket进行文件传输

c#中Socket进⾏⽂件传输Server段代码using System;using System.IO;using ;using .Sockets;using System.Text;using System.Threading;namespace SocketSendFileServer{class Program{const int BufferSize = 1024;static string path = @"E:\";static void Main(string[] args){IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080);Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);sock.Bind(ip);sock.Listen(1);Console.WriteLine("Begin listen...");while (true){Socket client = sock.Accept();if (client.Connected){Thread cThread = new Thread(new ParameterizedThreadStart(myClient));cThread.IsBackground = true;cThread.Start(client);}}}static void myClient(object oSocket){Socket clientSocket = (Socket)oSocket;string clientName = clientSocket.RemoteEndPoint.ToString();Console.WriteLine("新来⼀个客户:" + clientName);try{while (true){byte[] buffer = new byte[BufferSize];int count = clientSocket.Receive(buffer);Console.WriteLine("收到" + clientName + ":" + Encoding.Default.GetString(buffer, 0, count));string[] command = Encoding.Default.GetString(buffer, 0, count).Split(',');string fileName;long length;if (command[0] == "namelength"){fileName = command[1];length = Convert.ToInt64(command[2]);clientSocket.Send(Encoding.Default.GetBytes("OK"));long receive = 0L;Console.WriteLine("Receiveing file:" + fileName + ".Plz wait...");using (FileStream writer = new FileStream(bine(path, fileName), FileMode.Create, FileAccess.Write, FileShare.None)) {int received;while (receive < length){received = clientSocket.Receive(buffer);writer.Write(buffer, 0, received);writer.Flush();receive += (long)received;}}Console.WriteLine("Receive finish.\n");}}}catch{Console.WriteLine("客户:" + clientName + "退出");}}}}Client段代码using System;using System.IO;using ;using .Sockets;using System.Text;namespace SocketFileClient{class Program{static Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);static void Main(string[] args){sock.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080));Console.WriteLine("Connect successfully");while (true){Console.WriteLine("please input the path of the file which you want to send:");string path = Console.ReadLine();try{using (FileStream reader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None)) {long send = 0L, length = reader.Length;string sendStr = "namelength," + Path.GetFileName(path) + "," + length.ToString();string fileName = Path.GetFileName(path);sock.Send(Encoding.Default.GetBytes(sendStr));int BufferSize = 1024;byte[] buffer = new byte[32];sock.Receive(buffer);string mes = Encoding.Default.GetString(buffer);if (mes.Contains("OK")){Console.WriteLine("Sending file:" + fileName + ".Plz wait...");byte[] fileBuffer = new byte[BufferSize];int read, sent;while ((read = reader.Read(fileBuffer, 0, BufferSize)) != 0){sent = 0;while ((sent += sock.Send(fileBuffer, sent, read, SocketFlags.None)) < read){send += (long)sent;}}Console.WriteLine("Send finish.\n");}}}catch (Exception ex){Console.WriteLine(ex.Message);}}}}}。

socket传输文件的原理

socket传输文件的原理

socket传输文件的原理
文件传输是计算机网络中的一项基本功能,它允许在网络上的不同计算机之间共享和传输文件。

Socket是实现文件传输的一种常用方式,其原理如下:
1. 建立连接:在进行文件传输之前,需要在发送方和接收方之间建立连接。

这通常通过TCP/IP 协议实现,使用Socket进行连接的建立。

一旦连接建立成功,发送方和接收方就可以通过该连接进行数据传输。

2. 文件分割:由于文件通常较大,不适合一次性传输,因此需要将文件分割成较小的数据块。

这些数据块可以按照一定的顺序进行编号,以便于接收方重新组合成完整的文件。

3. 发送数据:发送方通过Socket将分割好的数据块逐个发送给接收方。

在发送数据时,需要按照一定的协议进行数据的封装,例如添加文件名、数据块大小等信息。

4. 接收数据:接收方通过Socket接收到数据后,需要按照发送方的协议对数据进行解析和处理。

接收方会将收到的数据块进行缓存,以便后续重新组合成完整的文件。

5. 确认机制:为了确保文件传输的完整性和正确性,发送方和接收方之间需要建立一种确认机制。

例如,发送方可以发送一个数据包的编号给接收方,接收方在收到数据包后回复一个确认信号给发送方,表示该数据包已经成功接收。

如果发送方在一定时间内没有收到确认信号,则会重新发送数据包,以确保数据的可靠传输。

6. 关闭连接:当文件传输完成后,发送方和接收方之间的连接会被关闭。

这可以通过Socket 的关闭函数实现,释放网络资源。

通过以上步骤,使用Socket可以实现文件的传输。

在实际应用中,不同的文件传输协议可能会有一些差异,但基本原理是相同的。

C语言基于socket的文件传输(可循环发送多个文件)

C语言基于socket的文件传输(可循环发送多个文件)

C语⾔基于socket的⽂件传输(可循环发送多个⽂件)基本简介:本次⽂件传输的实现主要是通过客户端向服务器发送下载请求,然后在服务器中找到对应的⽂件并打开⽂件,再继续向客户端传送⽂件,⽽客户端就在不停的接收。

这是因为⽂件可能⽐较⼤,⼀个缓冲数组只能保存⼀部分⽂件内容,因此服务器得不断从⽂件中读取内容并发给客户端,⽽客户端得不停的循环接收。

但是在事先,得将相应要发送的⽂件(照⽚,⾳频,视频等)保存在服务器相应的⽬录下。

⽽这个是不符合实际要求的,通常来讲,是应该将客户端1的⽂件发送给客户端2,⽽服务器仅仅只是起到⼀个中转站的作⽤,即⽂件应该事先保存在客户端1下。

这⾥我们只是完成⽂件传输的相应功能就⾏了,就不在计较这些啦。

因为只要你理解了这⼀块,可以根据⾃⼰的实际需要,在进⾏修改。

具体编译:gcc server.c -o server -lpthread //这是因为在服务器中加⼊了线程函数,所以编译的时候需要加上 -lpthread 。

gcc client.c -o client记住⼀定要先运⾏服务器,在运⾏客户端。

在客户端运⾏的时候回提醒你输⼊服务器对应的pc ip,如实输⼊就⾏啦。

如果是在本机pc上进⾏测试的话,也可以输⼊0.0.0.0 。

server.c:#include <stdio.h>#include <netdb.h>#include <sys/socket.h>#include <arpa/inet.h>#include <sys/types.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <netinet/in.h>#include <pthread.h>#define portnum 12345#define FILE_SIZE 500#define BUFFER_SIZE 1024void *net_thread(void * fd);int main(){//初始化套接字int server_fd=socket(AF_INET,SOCK_STREAM,0);if(-1==server_fd){perror("socket");exit(1);}//绑定端⼝和ip;struct sockaddr_in server_addr; //struct sockaddr_in为结构体类型,server_addr为定义的结构体server_addr.sin_family=AF_INET; //Internet地址族=AF_INET(IPv4协议)server_addr.sin_port=htons(portnum); //将主机字节序转化为⽹络字节序 ,portnum是端⼝号(server_addr.sin_addr).s_addr=htonl(INADDR_ANY);//IP地址if(-1==bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr))) //套接字与端⼝绑定{perror("bind");exit(6);}//开启监听if(-1==listen(server_fd,5)) //5是最⼤连接数,指服务器最多连接5个⽤户if(-1==listen(server_fd,5)) //5是最⼤连接数,指服务器最多连接5个⽤户{perror("listen");exit(7);}while(1){struct sockaddr_in client_addr;int size=sizeof(client_addr);int new_fd=accept(server_fd,(struct sockaddr *)&client_addr,&size); //server_fd服务器的socket描述字,&client_addr指向struct sockaddr *的指针,&size指向协议地址if(-1==new_fd){perror("accept");continue; //进⾏下⼀次循环}printf("accept client ip:%s:%d\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);//inet_ntoa将⼀个⼗进制⽹络字节序转换为点分⼗进制IP格式的字符串。

c++ 使用socket实现C%S端文件的下载传输

c++ 使用socket实现C%S端文件的下载传输

c++ 使用socket实现C/S端文件的下载传输首先是服务器端,大致说下流程:服务器创建线程去处理应答accept(),当接受到客户端连接请求时,首先获取要发送的指定的文件数据总大小给客户端,接着就是循环读取要发送的文件数据流向客户端发送文件数据,每次都判断循环读取到的数据实际大小,当实际读取到的数据总大小为0时,表示文件发送结束。

下面是服务器server端实现:声明部分:public:afx_msg void OnBnClickedButton1();public:BOOL InitSocket(); //初始化并创建套接字static DWORD WINAPI ThreadProc(LPVOID lpParameter); //创建线程去执行服务器accept()实现部分:void CSendFileServerDlg::OnBnClickedButton1(){// TODO: 在此添加控件通知处理程序代码if (InitSocket()){GetDlgItem(IDC_EDIT1)->SetWindowText(_T("服务器开启监听。

\r\n"));//创建线程HANDLE hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);//关闭该接收线程句柄,释放引用计数CloseHandle(hThread);}}BOOL CSendFileServerDlg::InitSocket(){//加载套接字库WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ){return FALSE;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ){WSACleanup( );return FALSE;}//创建套接字//SOCKET m_socket=socket(AF_INET,SOCK_STREAM,0);m_socket=socket(AF_INET,SOCK_STREAM,0);if (m_socket == INVALID_SOCKET){AfxMessageBox(_T("套接字创建失败!"));return FALSE;}SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(8099);err = bind(m_socket,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //绑定本地端口if (err==SOCKET_ERROR){closesocket(m_socket);AfxMessageBox(_T("绑定失败!"));return FALSE;}listen(m_socket,5);//开启监听return TRUE;}DWORD WINAPI CSendFileServerDlg::ThreadProc(LPVOID lpParameter){SOCKADDR_IN addrClient;int len = sizeof(SOCKADDR);while (true){SOCKET sockConn=accept(m_socket,(SOCKADDR*)&addrClient,&len);CString filename = _T("E:\\test.zip");HANDLE hFile;unsigned long long file_size = 0;char Buffer[1024];DWORD dwNumberOfBytesRead;hFile = CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_N ORMAL,NULL);file_size = GetFileSize(hFile,NULL);send(sockConn,(char*)&file_size,sizeof(unsigned long long)+1,NULL);do{::ReadFile(hFile,Buffer,sizeof(Buffer),&dwNumberOfBytesRead,NULL);::send(sockConn,Buffer,dwNumberOfBytesRead,0);} while (dwNumberOfBytesRead);CloseHandle(hFile);}return 0;}如代码所述每次发送单位是unsigned char[1024]大小(程序是char 应该为unsigned char[1024])所以就不存在网络字节序问题也不用考虑大端小端什么的。

C语言中send()函数和sendto()函数的使用方法

C语言中send()函数和sendto()函数的使用方法

C语⾔中send()函数和sendto()函数的使⽤⽅法C语⾔send()函数:经socket传送数据头⽂件:#include <sys/types.h> #include <sys/socket.h>定义函数:int send(int s, const void * msg, int len, unsigned int falgs);函数说明:send()⽤来将数据由指定的socket 传给对⽅主机. 参数s 为已建⽴好连接的socket. 参数msg 指向欲连线的数据内容,参数len 则为数据长度. 参数flags ⼀般设0, 其他数值定义如下:MSG_OOB 传送的数据以out-of-band 送出.MSG_DONTROUTE 取消路由表查询MSG_DONTWAIT 设置为不可阻断运作MSG_NOSIGNAL 此动作不愿被SIGPIPE 信号中断.返回值:成功则返回实际传送出去的字符数, 失败返回-1. 错误原因存于errno错误代码:EBADF 参数s ⾮合法的socket 处理代码.EFAULT 参数中有⼀指针指向⽆法存取的内存空间ENOTSOCK 参数s 为⼀⽂件描述词, ⾮socket.EINTR 被信号所中断.EAGAIN 此操作会令进程阻断, 但参数s 的socket 为不可阻断.ENOBUFS 系统的缓冲内存不⾜ENOMEM 核⼼内存不⾜EINVAL 传给系统调⽤的参数不正确.C语⾔sendto()函数:经socket传送数据头⽂件:#include <sys/types.h> #include <sys/socket.h>定义函数:int sendto(int s, const void * msg, int len, unsigned int flags, const struct sockaddr * to, int tolen);函数说明:sendto() ⽤来将数据由指定的socket 传给对⽅主机. 参数s 为已建好连线的socket, 如果利⽤UDP协议则不需经过连线操作. 参数msg 指向欲连线的数据内容, 参数flags ⼀般设0, 详细描述请参考send(). 参数to ⽤来指定欲传送的⽹络地址, 结构sockaddr 请参考bind(). 参数tolen 为sockaddr 的结果长度.返回值:成功则返回实际传送出去的字符数, 失败返回-1, 错误原因存于errno 中.错误代码:1、EBADF 参数s ⾮法的socket 处理代码.2、EFAULT 参数中有⼀指针指向⽆法存取的内存空间.3、WNOTSOCK canshu s 为⼀⽂件描述词, ⾮socket.4、EINTR 被信号所中断.5、EAGAIN 此动作会令进程阻断, 但参数s 的soket 为补课阻断的.6、ENOBUFS 系统的缓冲内存不⾜.7、EINVAL 传给系统调⽤的参数不正确.范例#include <sys/types.h>#include <sys/socket.h>#include <netinet.in.h>#include <arpa.inet.h>#define PORT 2345 /*使⽤的port */main(){int sockfd, len;struct sockaddr_in addr;char buffer[256];//建⽴socketif(sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror ("socket");exit(1);}//填写sockaddr_in 结构bzero(&addr, sizeof(addr));addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr = hton1(INADDR_ANY);if(bind(sockfd, &addr, sizeof(addr)) < 0){perror("connect");exit(1);}while(1){bezro(buffer, sizeof(buffer));len = recvfrom(socket, buffer, sizeof(buffer), 0, &addr &addr_len); //显⽰client 端的⽹络地址printf("receive from %s\n ", inet_ntoa(addr.sin_addr));//将字串返回给client 端sendto(sockfd, buffer, len, 0, &addr, addr_len);}}。

c# winform socket网络编程,点对点传输文件,socket文件传输,监听端口

c# winform socket网络编程,点对点传输文件,socket文件传输,监听端口

c# winform socket网络编程,点对点传输文件,socket文件传输,监听端口关键字: socket 网络编程点对点传输文件文件传输监听端口服务器用来接收文件,不停的监听端口,有发送文件就马上开始接收文件服务端代码:C#代码ing System;ing System.Collections.Generic;ing ponentModel;ing System.Data;ing System.Drawing;ing System.Text;ing System.Windows.Forms;8.9.ing ;ing System.Threading;ing .Sockets;13.ing System.IO;15.space TestSocketServerHSTF17.{18. public partial class Form1 : Form19. {20. public Form1()21. {22. InitializeComponent();23.24.25. //不显示出dataGridView1的最后一行空白26. dataGridView1.AllowUserToAddRows = false;27. }28.29.30. #region 定义变量31.32.33. #endregion34.36.37. #region 进入窗体即启动服务38.39. private void Form1_Load(object sender, EventArgs e)40. {41. //开启接收线程42. Thread TempThread = new Thread(new ThreadStart(this.StartReceive));43. TempThread.Start();44. }45.46.47. #endregion48.49.50.51. #region 功能函数52.53. private void StartReceive()54. {55. //创建一个网络端点56. IPEndPoint ipep = new IPEndPoint(IPAddress.Any, int.Parse("2005"));57.58. //MessageBox.Show(IPAddress.Any);59.60. //创建一个套接字61. Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);62.63. //绑定套接字到端口64. server.Bind(ipep);65.66. //开始侦听(并堵塞该线程)67. server.Listen(10);68.69. //确认连接70. Socket client = server.Accept();71.72. //获得客户端节点对象73. IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;74.76.77. //获得[文件名]78. string SendFileName = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));79. //MessageBox.Show("文件名" + SendFileName);80.81. //获得[包的大小]82. string bagSize = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));83. //MessageBox.Show("包大小" + bagSize);84.85. //获得[包的总数量]86. int bagCount = int.Parse(System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client)));87. //MessageBox.Show("包的总数量" + bagCount);88.89. //获得[最后一个包的大小]90. string bagLast = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));91. //MessageBox.Show("最后一个包的大小" + bagLast);92.93. //创建一个新文件94. FileStream MyFileStream = new FileStream(SendFileName, FileMode.Create, FileAccess.Write);95.96. //已发送包的个数97. int SendedCount = 0;98.99. while (true)100. {101. byte[] data = TransferFiles.ReceiveVarData (client);102. if (data.Length == 0)103. {104. break;105. }106. else107. {108. SendedCount++;109. //将接收到的数据包写入到文件流对象110. MyFileStream.Write(data, 0, data.Length);111. //显示已发送包的个数112. //MessageBox.Show("已发送包个数"+SendedCount.ToString());113. }114. }115.116. //关闭文件流117. MyFileStream.Close();118. //关闭套接字119. client.Close();120.121. //填加到dgv里122. //文件大小,IP,已发送包的个数,文件名,包的总量,最后一个包的大小123. this.dataGridView1.Rows.Add(bagSize, clientep.Address, SendedCount, SendFileName, bagCount, bagLast); 124.125. //MessageBox.Show("文件接收完毕!");126.127. }128.129.130. #endregion131.132.133.134. #region 拦截Windows消息,关闭窗体时执行135. protected override void WndProc(ref Message m)136. {137. const int WM_SYSCOMMAND = 0x0112;138. const int SC_CLOSE = 0xF060;139. if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)140. {//捕捉关闭窗体消息141. // User clicked close button 142. //this.WindowState = FormWindowState.Minim ized;//把右上角红叉关闭按钮变最小化143.144. ServiceStop();145. }146. base.WndProc(ref m);147. }148. #endregion149.150.151. #region 停止服务152.153. //停止服务154. private void ServiceStop()155. {156. try157. {158.159. }160. catch { }161.162. try163. {164.165. }166. catch { }167. }168.169. #endregion170.171. }172.}客户端用来发送文件,选择文件后点发送按钮发送文件客户端代码:C#代码1.////////////////////////////////////////////////////////////////////////////////2.//title: 点对点文件传输程序 //3.////////////////////////////////////////////////////////////////////////////////4.5.//////////////////////////Begin-发送端//////////////////////////////////ing System;ing System.Drawing;ing System.Collections;ing ponentModel;ing System.Windows.Forms;ing System.Data;ing System.IO;ing ;ing .Sockets;ing System.Threading;16.space 发送端18.{19. /// <summary>20. /// Form1 的摘要说明。

C#socket多线程多管道可断点传送大文件(附单线程单管道传送)

C#socket多线程多管道可断点传送大文件(附单线程单管道传送)

C#socket多线程多管道可断点传送⼤⽂件(附单线程单管道传送)这⾥只发布核⼼代码。

源码及测试程序请点下载,谢谢。

有啥BUG,问题请发送email⾄,谢谢。

:D代码1#define Sleep2//#undef Sleep3 //#define TransmitLog4#undef TransmitLog5//#define BreakpointLog6#undef BreakpointLog7using System;8using ;9using .Sockets;10using System.IO;11using System.Text;12using System.Threading;13using System.Collections.Generic;14using System.Diagnostics;1516namespace Rocky17 {18public static class FileTransmiter19 {20#region NestedType21private class SendWorker : IWorker22 {23private long totalSent, totalSend;24private byte[] buffer;25private Socket sock;26private FileStream reader;27private Thread thread;28private bool isFinished;2930public long TotalSent31 {32get { return totalSent; }33 }34public long TotalSend35 {36get { return totalSend; }37 }38public byte[] Buffer39 {40get { return buffer; }41 }42public Socket Client43 {44get { return sock; }45 }46public bool IsFinished47 {48get { return isFinished; }49 }5051public SendWorker(IPEndPoint ip)52 {53 sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);54 sock.Connect(ip);55 buffer = new byte[BufferSize];56 }57public void Initialize(string path, long position, long length)58 {59 Initialize(path, position, length, 0L, length);60 }61public void Initialize(string path, long position, long length, long worked, long total)62 {63 reader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);64 reader.Position = position + worked;65 totalSent = worked;66 totalSend = total;67 thread = new Thread(new ParameterizedThreadStart(Work));68 thread.IsBackground = true;69#if TransmitLog70 = position.ToString() + length.ToString();71 AppendTransmitLog(LogType.Transmit, + " Initialized:" + totalSent + "/" + totalSend + ".");72#endif73 }74private void Work(object obj)75 {76int read, sent;77bool flag;78while (totalSent < totalSend)79 {80 read = reader.Read(buffer, 0, Math.Min(BufferSize, (int)(totalSend - totalSent)));81 sent = 0;82 flag = true;83while ((sent += sock.Send(buffer, sent, read, SocketFlags.None)) < read)84 {85 flag = false;86 totalSent += (long)sent;87#if TransmitLog88 AppendTransmitLog(LogType.Transmit, + ":" + totalSent + "/" + totalSend + "."); 89#endif90#if Sleep91 Thread.Sleep(200);92#endif93 }94if (flag)95 {96 totalSent += (long)read;97#if TransmitLog98 AppendTransmitLog(LogType.Transmit, + ":" + totalSent + "/" + totalSend + "."); 99#endif100#if Sleep101 Thread.Sleep(200);102#endif103 }104 }105 reader.Dispose();106 sock.Shutdown(SocketShutdown.Both);107 sock.Close();108 EventWaitHandle waitHandle = obj as EventWaitHandle;109if (waitHandle != null)110 {111 waitHandle.Set();112 }113 isFinished = true;114 }115116public void ReportProgress(out long worked, out long total)117 {118 worked = totalSent;119 total = totalSend;120 }121122public void RunWork(EventWaitHandle waitHandle)123 {124 thread.Start(waitHandle);125 }126 }127128private class ReceiveWorker : IWorker129 {130private long offset, totalReceived, totalReceive;131private byte[] buffer;132private Socket sock;133private FileStream writer;134private Thread thread;135private bool isFinished;136137public long TotalReceived138 {139get { return totalReceived; }140 }141public long TotalReceive142 {143get { return totalReceive; }144 }145public byte[] Buffer146 {147get { return buffer; }148 }149public Socket Client150 {151get { return sock; }152 }153public bool IsFinished154 {155get { return isFinished; }156 }157158public ReceiveWorker(Socket client)159 {160 sock = client;161 buffer = new byte[BufferSize];162 }163public void Initialize(string path, long position, long length)164 {165 Initialize(path, position, length, 0L, length);166 }167public void Initialize(string path, long position, long length, long worked, long total)168 {169 writer = new FileStream(path, FileMode.Open, FileAccess.Write, FileShare.Write);170 writer.Position = position + worked;171 writer.Lock(position, length);172 offset = position;173 totalReceived = worked;174 totalReceive = total;175 thread = new Thread(new ParameterizedThreadStart(Work));176 thread.IsBackground = true;177#if TransmitLog178 = position.ToString() + length.ToString();179 AppendTransmitLog(LogType.Transmit, + " Initialized:" + totalReceived + "/" + totalReceive + ".");180#endif181 }182private void Work(object obj)183 {184int received;185while (totalReceived < totalReceive)186 {187if ((received = sock.Receive(buffer)) == 0)188 {189break;190 }191 writer.Write(buffer, 0, received);192 writer.Flush();193 totalReceived += (long)received;194#if TransmitLog195 AppendTransmitLog(LogType.Transmit, + ":" + totalReceived + "/" + totalReceive + ".");196#endif197#if Sleep198 Thread.Sleep(200);199#endif200 }201 writer.Unlock(offset, totalReceive);202 writer.Dispose();203 sock.Shutdown(SocketShutdown.Both);204 sock.Close();205 EventWaitHandle waitHandle = obj as EventWaitHandle;206if (waitHandle != null)207 {208 waitHandle.Set();209 }210 isFinished = true;211 }212213public void ReportProgress(out long worked, out long total)214 {215 worked = totalReceived;216 total = totalReceive;217 }218219public void RunWork(EventWaitHandle waitHandle)220 {221 thread.Start(waitHandle);222 }223 }224225private interface IWorker226 {227bool IsFinished { get; }228void Initialize(string path, long position, long length);229void Initialize(string path, long position, long length, long worked, long total);230void ReportProgress(out long worked, out long total);231void RunWork(EventWaitHandle waitHandle);232 }233#endregion234235#region Field236public const int BufferSize = 1024;237public const int PerLongCount = sizeof(long);238public const int MinThreadCount = 1;239public const int MaxThreadCount = 9;240public const string PointExtension = ".dat";241public const string TempExtension = ".temp";242private const long SplitSize = 1024L * 1024L * 100L;243public static readonly IPEndPoint TestIP;244#if TransmitLog245private static StreamWriter transmitLoger;246#endif247#if BreakpointLog248private static StreamWriter breakpointLoger;249#endif250#endregion251252#region Constructor253static FileTransmiter()254 {255 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);256 TestIP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 520);257#if TransmitLog258 transmitLoger = new StreamWriter(bine(AppDomain.CurrentDomain.BaseDirectory, "transmit.log"), true, Encoding.Default); 259#endif260#if BreakpointLog261 breakpointLoger = new StreamWriter(bine(AppDomain.CurrentDomain.BaseDirectory, "breakpoint.log"), true, Encoding.Default); 262#endif263 }264265static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)266 {267 StreamWriter writer = new StreamWriter(bine(AppDomain.CurrentDomain.BaseDirectory, "exec.log"), true, Encoding.Default); 268 writer.Write("Time:");269 writer.Write(DateTime.Now.ToShortTimeString());270 writer.Write(". ");271 writer.WriteLine(e.ExceptionObject);272 writer.Dispose();273 }274275#region Log276#if TransmitLog || BreakpointLog277public enum LogType278 {279 Transmit,280 Breakpoint281 }282283public static void AppendTransmitLog(LogType type, string msg)284 {285switch (type)286 {287case LogType.Transmit:288#if TransmitLog289 transmitLoger.Write(DateTime.Now.ToShortTimeString());290 transmitLoger.Write('\t');291 transmitLoger.WriteLine(msg);292 transmitLoger.Flush();293#endif294break;295case LogType.Breakpoint:296#if BreakpointLog297 breakpointLoger.Write(DateTime.Now.ToShortTimeString());298 breakpointLoger.Write('\t');299 breakpointLoger.WriteLine(msg);300 breakpointLoger.Flush();301#endif302break;303 }304 }305#endif306#endregion307#endregion308309#region Single310public static void Send(IPEndPoint ip, string path)311 {312 Stopwatch watcher = new Stopwatch();313 watcher.Start();314 Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);315 sock.Connect(ip);316byte[] buffer = new byte[BufferSize];317using (FileStream reader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None))318 {319long send, length = reader.Length;320 Buffer.BlockCopy(BitConverter.GetBytes(length), 0, buffer, 0, PerLongCount);321string fileName = Path.GetFileName(path);322 sock.Send(buffer, 0, PerLongCount + Encoding.Default.GetBytes(fileName, 0, fileName.Length, buffer, PerLongCount), SocketFlags.None); 323 Console.WriteLine("Sending file:" + fileName + ".Plz wait...");324 sock.Receive(buffer);325 reader.Position = send = BitConverter.ToInt64(buffer, 0);326#if BreakpointLog327 Console.WriteLine("Breakpoint " + reader.Position);328#endif329int read, sent;330bool flag;331while ((read = reader.Read(buffer, 0, BufferSize)) != 0)332 {333 sent = 0;334 flag = true;335while ((sent += sock.Send(buffer, sent, read, SocketFlags.None)) < read)336 {337 flag = false;338 send += (long)sent;339#if TransmitLog340 Console.WriteLine("Sent " + send + "/" + length + ".");341#endif342#if Sleep343 Thread.Sleep(200);344#endif345 }346if (flag)347 {348 send += (long)read;349#if TransmitLog350 Console.WriteLine("Sent " + send + "/" + length + ".");351#endif352#if Sleep353 Thread.Sleep(200);354#endif355 }356 }357 }358 sock.Shutdown(SocketShutdown.Both);359 sock.Close();360 watcher.Stop();361 Console.WriteLine("Send finish.Span Time:" + watcher.Elapsed.TotalMilliseconds + " ms.");362 }363364public static void Receive(IPEndPoint ip, string path)365 {366 Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);367 listener.Bind(ip);368 listener.Listen(MinThreadCount);369 Socket client = listener.Accept();370 Stopwatch watcher = new Stopwatch();371 watcher.Start();372byte[] buffer = new byte[BufferSize];373int received = client.Receive(buffer);374long receive, length = BitConverter.ToInt64(buffer, 0);375string fileName = Encoding.Default.GetString(buffer, PerLongCount, received - PerLongCount);376 Console.WriteLine("Receiveing file:" + fileName + ".Plz wait...");377 FileInfo file = new FileInfo(bine(path, fileName));378using (FileStream writer = file.Open(file.Exists ? FileMode.Append : FileMode.CreateNew, FileAccess.Write, FileShare.None)) 379 {380 receive = writer.Length;381 client.Send(BitConverter.GetBytes(receive));382#if BreakpointLog383 Console.WriteLine("Breakpoint " + receive);384#endif385while (receive < length)386 {387if ((received = client.Receive(buffer)) == 0)388 {389 Console.WriteLine("Send Stop.");390return;391 }392 writer.Write(buffer, 0, received);393 writer.Flush();394 receive += (long)received;395#if TransmitLog396 Console.WriteLine("Received " + receive + "/" + length + ".");397#endif398#if Sleep399 Thread.Sleep(200);400#endif401 }402 }403 client.Shutdown(SocketShutdown.Both);404 client.Close();405 watcher.Stop();406 Console.WriteLine("Receive finish.Span Time:" + watcher.Elapsed.TotalMilliseconds + " ms.");407 }408#endregion409410#region Supper411#region Extensions412private static int ReportProgress(this IWorker[] workers, out long worked, out long total)413 {414 worked = total = 0L;415long w, t;416foreach (IWorker worker in workers)417 {418 worker.ReportProgress(out w, out t);419 worked += w;420 total += t;421 }422return (int)(worked / total) * 100;423 }424private static int ReportSpeed(this IWorker[] workers, ref long oldValue)425 {426long w, t;427 workers.ReportProgress(out w, out t);428int speed = (int)((w - oldValue) / 8L);429 oldValue = w;430return speed;431 }432private static bool IsAllFinished(this IWorker[] workers)433 {434bool flag = true;435foreach (IWorker worker in workers)436 {437if (!worker.IsFinished)438 {439 flag = false;440break;441 }442 }443return flag;444 }445#endregion446447#region Helper448public static void Write(long value, byte[] buffer, int offset)449 {450 buffer[offset++] = (byte)value;451 buffer[offset++] = (byte)(value >> 8);452 buffer[offset++] = (byte)(value >> 0x10);453 buffer[offset++] = (byte)(value >> 0x18);454 buffer[offset++] = (byte)(value >> 0x20);455 buffer[offset++] = (byte)(value >> 40);456 buffer[offset++] = (byte)(value >> 0x30);457 buffer[offset] = (byte)(value >> 0x38);458 }459public static void Read(out long value, byte[] buffer, int offset)460 {461uint num = (uint)(((buffer[offset++] | (buffer[offset++] << 8)) | (buffer[offset++] << 0x10)) | (buffer[offset++] << 0x18));462uint num2 = (uint)(((buffer[offset++] | (buffer[offset++] << 8)) | (buffer[offset++] << 0x10)) | (buffer[offset] << 0x18));463 value = (long)((num2 << 0x20) | num);464 }465#endregion466467public static int GetThreadCount(long fileSize)468 {469int count = (int)(fileSize / SplitSize);470if (count < MinThreadCount)471 {472 count = MinThreadCount;473 }474else if (count > MaxThreadCount)475 {476 count = MaxThreadCount;477 }478return count;479 }480481public static void SupperSend(IPEndPoint ip, string path)482 {483 Stopwatch watcher = new Stopwatch();484 watcher.Start();485 FileInfo file = new FileInfo(path);486#if DEBUG487if (!file.Exists)488 {489throw new FileNotFoundException();490 }491#endif492 SendWorker worker = new SendWorker(ip);493long fileLength = file.Length;494 Buffer.BlockCopy(BitConverter.GetBytes(fileLength), 0, worker.Buffer, 0, PerLongCount);495string fileName = ;496 worker.Client.Send(worker.Buffer, 0, PerLongCount + Encoding.Default.GetBytes(fileName, 0, fileName.Length, worker.Buffer, PerLongCount), SocketFlags.None); 497 Console.WriteLine("Sending file:" + fileName + ".Plz wait...");498int threadCount = GetThreadCount(fileLength);499 SendWorker[] workers = new SendWorker[threadCount];500for (int i = 0; i < threadCount; i++)501 {502 workers[i] = i == 0 ? worker : new SendWorker(ip);503 }504#region Breakpoint505int perPairCount = PerLongCount * 2, count = perPairCount * threadCount;506byte[] bufferInfo = new byte[count];507long oddSize, avgSize = Math.DivRem(fileLength, (long)threadCount, out oddSize);508if (worker.Client.Receive(bufferInfo) == 4)509 {510for (int i = 0; i < threadCount; i++)511 {512 workers[i].Initialize(path, i * avgSize, i == threadCount - 1 ? avgSize + oddSize : avgSize);513 }514 }515else516 {517long w, t;518for (int i = 0; i < threadCount; i++)519 {520 Read(out w, bufferInfo, i * perPairCount);521 Read(out t, bufferInfo, i * perPairCount + PerLongCount);522 workers[i].Initialize(path, i * avgSize, i == threadCount - 1 ? avgSize + oddSize : avgSize, w, t);523#if BreakpointLog524 AppendTransmitLog(LogType.Breakpoint, i + " read:" + w + "/" + t + ".");525#endif526 }527 }528 Thread.Sleep(200);529#endregion530 AutoResetEvent reset = new AutoResetEvent(true);531for (int i = 0; i < threadCount; i++)532 {533 workers[i].RunWork(i == threadCount - 1 ? reset : null);534 }535 reset.WaitOne();536#region Breakpoint537int speed;538long value = 0L;539do540 {541 speed = workers.ReportSpeed(ref value);542 Console.WriteLine("waiting for other threads. Progress:" + value + "/" + fileLength + ";Speed:" + speed + "kb/s.");543 Thread.Sleep(1000);544 }545while (!workers.IsAllFinished());546 speed = workers.ReportSpeed(ref value);547 Console.WriteLine("waiting for other threads. Progress:" + value + "/" + fileLength + ";Speed:" + speed + "kb/s.");548#endregion549 watcher.Stop();550 Console.WriteLine("Send finish.Span Time:" + watcher.Elapsed.TotalMilliseconds + " ms.");551 }552553public static void SupperReceive(IPEndPoint ip, string path)554 {555 Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);556 listener.Bind(ip);557 listener.Listen(MaxThreadCount);558 ReceiveWorker worker = new ReceiveWorker(listener.Accept());559 Stopwatch watcher = new Stopwatch();560 watcher.Start();561int recv = worker.Client.Receive(worker.Buffer);562long fileLength = BitConverter.ToInt64(worker.Buffer, 0);563string fileName = Encoding.Default.GetString(worker.Buffer, PerLongCount, recv - PerLongCount);564 Console.WriteLine("Receiveing file:" + fileName + ".Plz wait...");565int threadCount = GetThreadCount(fileLength);566 ReceiveWorker[] workers = new ReceiveWorker[threadCount];567for (int i = 0; i < threadCount; i++)568 {569 workers[i] = i == 0 ? worker : new ReceiveWorker(listener.Accept());570 }571#region Breakpoint572int perPairCount = PerLongCount * 2, count = perPairCount * threadCount;573byte[] bufferInfo = new byte[count];574string filePath = bine(path, fileName), pointFilePath = Path.ChangeExtension(filePath, PointExtension), tempFilePath = Path.ChangeExtension(filePath, TempExtension); 575 FileStream pointStream;576long oddSize, avgSize = Math.DivRem(fileLength, (long)threadCount, out oddSize);577if (File.Exists(pointFilePath) && File.Exists(tempFilePath))578 {579 pointStream = new FileStream(pointFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);580 pointStream.Read(bufferInfo, 0, count);581long w, t;582for (int i = 0; i < threadCount; i++)583 {584 Read(out w, bufferInfo, i * perPairCount);585 Read(out t, bufferInfo, i * perPairCount + PerLongCount);586 workers[i].Initialize(tempFilePath, i * avgSize, i == threadCount - 1 ? avgSize + oddSize : avgSize, w, t);587#if BreakpointLog588 AppendTransmitLog(LogType.Breakpoint, i + " read:" + w + "/" + t + ".");589#endif590 }591 worker.Client.Send(bufferInfo);592 }593else594 {595 pointStream = new FileStream(pointFilePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None);596 FileStream stream = new FileStream(tempFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Write);597 stream.SetLength(fileLength);598 stream.Flush();599 stream.Dispose();600for (int i = 0; i < threadCount; i++)601 {602 workers[i].Initialize(tempFilePath, i * avgSize, i == threadCount - 1 ? avgSize + oddSize : avgSize);603 }604 worker.Client.Send(bufferInfo, 0, 4, SocketFlags.None);605 }606 Timer timer = new Timer(state =>607 {608long w, t;609for (int i = 0; i < threadCount; i++)610 {611 workers[i].ReportProgress(out w, out t);612 Write(w, bufferInfo, i * perPairCount);613 Write(t, bufferInfo, i * perPairCount + PerLongCount);614#if BreakpointLog615 AppendTransmitLog(LogType.Breakpoint, i + " write:" + w + "/" + t + ".");616#endif617 }618 pointStream.Position = 0L;619 pointStream.Write(bufferInfo, 0, count);620 pointStream.Flush();621622 }, null, TimeSpan.Zero, TimeSpan.FromSeconds(2));623#endregion624 AutoResetEvent reset = new AutoResetEvent(true);625for (int i = 0; i < threadCount; i++)626 {627 workers[i].RunWork(i == threadCount - 1 ? reset : null);628 }629 reset.WaitOne();630#region Breakpoint631int speed;632long value = 0L;633do634 {635 speed = workers.ReportSpeed(ref value);636 Console.WriteLine("waiting for other threads. Progress:" + value + "/" + fileLength + ";Speed:" + speed + "kb/s.");637 Thread.Sleep(1000);638 }639while (!workers.IsAllFinished());640 speed = workers.ReportSpeed(ref value);641 Console.WriteLine("waiting for other threads. Progress:" + value + "/" + fileLength + ";Speed:" + speed + "kb/s.");642 timer.Dispose();643 pointStream.Dispose();644 File.Delete(pointFilePath);645 File.Move(tempFilePath, filePath);646#endregion647 watcher.Stop();648 Console.WriteLine("Receive finish.Span Time:" + watcher.Elapsed.TotalMilliseconds + " ms.");649 }650#endregion651 }652 }PS:1、通过测试发现多线程stream.Flush()的地⽅会阻塞,可以尝试增⼤stream的缓冲区或⼿动管理调⽤stream的Flush()。

socket完成文件传输的原理

socket完成文件传输的原理

socket完成文件传输的原理
Socket是计算机网络编程中常用的一种通信方式,它通过网络将数据传输到远程主机。

而文件传输则是Socket通信中经常需要实现的功能之一。

实现文件传输的原理如下:
1. 建立Socket连接:在进行文件传输前,需要建立Socket连接。

客户端和服务器之间都需要创建一个套接字(socket),并通过该套接字建立网络连接。

2. 打开文件:在进行文件传输前,需要先打开要传输的文件。

客户端和服务器都需要先打开相应的文件,并且需要知道文件的路径和文件名。

3. 读取文件内容并发送:客户端将要传输的文件读取到内存中,然后通过Socket发送给服务器。

服务器接收客户端发送的数据,并将数据写入到本地硬盘上。

同样地,服务器也可以将要传输的文件读取到内存中,然后通过Socket发送给客户端。

4. 关闭Socket连接和文件:在文件传输完成后,客户端和服务器都需要关闭Socket连接,并且关闭相应的文件。

综上所述,Socket完成文件传输的原理就是通过Socket连接发送文件内容,实现文件传输。

客户端将要传输的文件读取到内存中,并通过Socket发送给服务器,服务器接收到数据后将其写入本地硬盘上。

同样地,服务器也可以将要传输的文件读取到内存中,并通过Socket发送给客户端。

完成文件传输后,客户端和服务器都需要关闭Socket连接和相应的文件。

LinuxCC++TCPSocket传输文件或图片实例

LinuxCC++TCPSocket传输文件或图片实例

LinuxCC++TCPSocket传输⽂件或图⽚实例环境:Linux语⾔:C/C++通信⽅式:TCP 下⾯⽤TCP协议编写⼀个简单的服务器、客户端,其中服务器端⼀直监听本机的6666号端⼝。

如果收到连接请求,将接收请求并接收客户端发来的消息;客户端与服务器端建⽴连接。

连接建⽴成功后,读取⽂件内容(/root/workspace/socket-picture/bizhi.jpg),发送给服务器端,服务器端新建new1.jpg⽂件,将接收到的⽂件内容保存到new1.jpg中,new1.jpg在当前⽬录下;Server.cpp1 #include<stdio.h>2 #include<stdlib.h>3 #include<string.h>4 #include<errno.h>5 #include<sys/types.h>6 #include<sys/socket.h>7 #include<netinet/in.h>8 #include<unistd.h>910#define MAXLINE 40961112int main(int argc, char** argv){13int listenfd, connfd;14struct sockaddr_in servaddr;15char buff[4096];16 FILE *fp;17int n;1819if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){20 printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);21return0;22 }23 printf("----init socket----\n");2425 memset(&servaddr, 0, sizeof(servaddr));26 servaddr.sin_family = AF_INET;27 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);28 servaddr.sin_port = htons(6666);29//设置端⼝可重⽤30int contain;31 setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &contain, sizeof(int));3233if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){34 printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);35return0;36 }37 printf("----bind sucess----\n");3839if( listen(listenfd, 10) == -1){40 printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);41return0;42 }43if((fp = fopen("new1.jpg","ab") ) == NULL )44 {45 printf("File.\n");46 close(listenfd);47 exit(1);48 }4950 printf("======waiting for client's request======\n");51while(1){52struct sockaddr_in client_addr;53 socklen_t size=sizeof(client_addr);54if( (connfd = accept(listenfd, (struct sockaddr*)&client_addr, &size)) == -1){55 printf("accept socket error: %s(errno: %d)",strerror(errno),errno);56continue;57 }58while(1){59 n = read(connfd, buff, MAXLINE);60if(n == 0)61break;62 fwrite(buff, 1, n, fp);63 }64 buff[n] = '\0';65 printf("recv msg from client: %s\n", buff);66 close(connfd);67 fclose(fp);68 }69 close(listenfd);70return0;71 }Client.cpp1 #include <stdio.h>2 #include <errno.h>3 #include <string.h>4 #include <netdb.h>5 #include <sys/types.h>6 #include <netinet/in.h>7 #include <sys/socket.h>8 #include <stdlib.h>9 #include <unistd.h>10 #include <arpa/inet.h>11 #include <netdb.h>12#define MAXLINE 40961314int main(int argc, char** argv){15int sockfd, len;16char buffer[MAXLINE];17struct sockaddr_in servaddr;18 FILE *fq;1920if( argc != 2){21 printf("usage: ./client <ipaddress>\n");22return0;23 }2425if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){26 printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);27return0;28 }2930 memset(&servaddr, 0, sizeof(servaddr));31 servaddr.sin_family = AF_INET;32 servaddr.sin_port = htons(6666);33if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){34 printf("inet_pton error for %s\n",argv[1]);35return0;36 }3738if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ 39 printf("connect error: %s(errno: %d)\n",strerror(errno),errno);40return0;41 }42if( ( fq = fopen("/root/workspace/socket-picture/bizhi.jpg","rb") ) == NULL ){43 printf("File open.\n");44 close(sockfd);45 exit(1);46 }4748 bzero(buffer,sizeof(buffer));49while(!feof(fq)){50 len = fread(buffer, 1, sizeof(buffer), fq);51if(len != write(sockfd, buffer, len)){52 printf("write.\n");53break;54 }55 }56 close(sockfd);57 fclose(fq);5859return0;60 }makefile1 all:server client2 server:server.o3 g++ -g -o server server.o4 client:client.o5 g++ -g -o client client.o6 server.o:server.cpp7 g++ -g -c server.cpp8 client.o:client.cpp9 g++ -g -c client.cpp10 clean:all11 rm all 执⾏make命令后,⽣成server和client两个可执⾏⽂件。

c++socket文件传输实现思路

c++socket文件传输实现思路

c++socket文件传输实现思路在C++中使用套接字(sockets)进行文件传输通常涉及到客户端和服务器端的通信。

下面是一个简单的文件传输实现思路,包含一个简单的服务器和客户端。

服务器端实现思路:1. 创建套接字:使用`socket()`函数创建一个套接字。

2. 绑定套接字:使用`bind()`函数将套接字绑定到一个特定的端口。

3. 监听连接请求:使用`listen()`函数监听来自客户端的连接请求。

4. 接受连接:使用`accept()`函数接受客户端的连接请求,返回一个新的套接字用于与该客户端通信。

5. 接收文件信息:接受客户端发送的文件信息,包括文件名和文件大小。

6. 接收文件数据:根据文件大小,使用`recv()`函数多次接收文件数据。

7. 保存文件:将接收到的文件数据保存到服务器上的文件。

8. 关闭套接字:在文件传输完成后,关闭套接字。

客户端端实现思路:1. 创建套接字:使用`socket()`函数创建一个套接字。

2. 连接服务器:使用`connect()`函数连接到服务器的地址和端口。

3. 打开文件:打开要传输的文件,获取文件名和文件大小。

4. 发送文件信息:发送文件信息给服务器,包括文件名和文件大小。

5. 发送文件数据:按照设定的数据块大小,多次使用`send()`函数发送文件数据。

6. 关闭套接字:在文件传输完成后,关闭套接字。

下面是一个简单的例子,涉及到服务器端和客户端的基本实现:服务器端代码:```cpp#include <iostream>#include <fstream>#include <sstream>#include <cstring>#include <sys/socket.h>#include <netinet/in.h>int main() {// 创建套接字int serverSocket = socket(AF_INET, SOCK_STREAM, 0);// 绑定套接字到端口sockaddr_in serverAddress;serverAddress.sin_family = AF_INET;serverAddress.sin_port = htons(12345);serverAddress.sin_addr.s_addr = INADDR_ANY;bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));// 监听连接请求listen(serverSocket, 5);// 接受连接int clientSocket = accept(serverSocket, NULL, NULL);// 接收文件信息char buffer[1024];recv(clientSocket, buffer, sizeof(buffer), 0);std::istringstream iss(buffer);std::string fileName;std::size_t fileSize;iss >> fileName >> fileSize;// 接收文件数据并保存到服务器上std::ofstream outputFile(fileName, std::ios::binary);while (fileSize > 0) {std::size_t bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);outputFile.write(buffer, bytesRead);fileSize -= bytesRead;}// 关闭套接字close(clientSocket);close(serverSocket);}```客户端代码:```cpp#include <iostream>#include <fstream>#include <sstream>#include <cstring>#include <sys/socket.h>#include <netinet/in.h>int main() {// 创建套接字int clientSocket = socket(AF_INET, SOCK_STREAM, 0);// 连接到服务器sockaddr_in serverAddress;serverAddress.sin_family = AF_INET;serverAddress.sin_port = htons(12345);serverAddress.sin_addr.s_addr = inet_addr("server_ip_address");connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));// 打开文件std::ifstream inputFile("file_to_send.txt", std::ios::binary);std::ostringstream oss;oss << "file_to_send.txt " << inputFile.tellg();std::string fileInfo = oss.str();// 发送文件信息send(clientSocket, fileInfo.c_str(), fileInfo.size(), 0);// 发送文件数据char buffer[1024];while (!inputFile.eof()) {inputFile.read(buffer, sizeof(buffer));send(clientSocket, buffer, inputFile.gcount(), 0);}// 关闭套接字close(clientSocket);}```请注意,上述代码只是一个基本示例,可能需要根据实际需求进行改进和优化。

linux创建socket收发链路层报文的c语言代码

linux创建socket收发链路层报文的c语言代码

linux创建socket收发链路层报文的c语言代码引言概述:在Linux操作系统中,使用C语言编写代码可以创建socket并进行收发链路层报文的操作。

本文将详细介绍如何使用C语言编写代码来实现这一功能。

正文内容:1. socket的创建1.1. 引入必要的头文件:在C语言代码中,需要引入一些必要的头文件,如<sys/types.h>、<sys/socket.h>和<netinet/in.h>等,以便使用相关的函数和数据结构。

1.2. 创建socket:使用socket()函数可以创建一个socket,该函数需要指定协议族、套接字类型和协议类型等参数。

常用的协议族有AF_PACKET(链路层协议族)、AF_INET(IPv4协议族)和AF_INET6(IPv6协议族)等。

1.3. 设置socket选项:可以使用setsockopt()函数来设置socket的选项,如设置接收和发送缓冲区的大小等。

2. 绑定socket2.1. 创建一个用于绑定的结构体:使用struct sockaddr_ll结构体来保存链路层地址信息,包括接口索引、协议类型和目标MAC地址等。

2.2. 绑定socket:使用bind()函数将socket与特定的链路层地址绑定,以便接收和发送链路层报文。

3. 发送链路层报文3.1. 构建报文:使用C语言的数据结构和函数来构建链路层报文,包括设置目标MAC地址、源MAC地址、协议类型和数据等。

3.2. 发送报文:使用sendto()函数发送链路层报文,该函数需要指定socket、报文数据和报文长度等参数。

4. 接收链路层报文4.1. 创建一个接收缓冲区:使用malloc()函数动态分配一个足够大的缓冲区来接收链路层报文。

4.2. 接收报文:使用recvfrom()函数接收链路层报文,该函数需要指定socket、接收缓冲区和缓冲区大小等参数。

5. 关闭socket5.1. 关闭socket:使用close()函数关闭已创建的socket,释放相关资源。

C#Socket单向请求文件传输[扩展断点续传]

C#Socket单向请求文件传输[扩展断点续传]

C#Socket单向请求⽂件传输[扩展断点续传]由于是单向请求,就是说主动的只有客户端。

当客户端上传⽂件的时候,需要先传给服务端⼀个数据,告诉服务端它将要上传⽂件以及⽂件的⼤⼩,客户端要求的分包⼤⼩,将要发送的分包个数,原路径,⽬标路径等等,服务端根据这个信息查找临时⽂件,看是否接受过此⽂件,如果接受过,服务端发送⼀条数据给客户端告诉客户端,已经接受到的⽂件⼤⼩,分包个数,分包⼤⼩,然后客户端调整分包⼤⼩,发送⼀条数据到服务端,告诉服务端它协议解析正确开始发送数据,服务端发送确认消息,客户端开始发送⽂件数据,服务端开始接受⽂件数据并将其写⼊⽂件,发送完成之后,客户端发数据告诉服务端发送完成,服务端核对⽂件信息,发送确认信息给客户端,关闭socket链接。

当客户端下载⽂件的时候,需要先传给服务端⼀个数据,告诉服务端它将要下载⽂件,客户端要求的分包⼤⼩,原路径,⽬标路径,已经接受的分包个数,分包⼤⼩等等,服务端根据这个信息查找⽂件,发送⼀条数据给客户端告诉客户端⽂件⼤⼩,分包个数,分包⼤⼩,然后客户端发送⼀条数据到服务端,告诉服务端它协议解析正确开始接受数据,服务端发送确认消息,服务端开始发送⽂件数据,客户端开始接受⽂件数据并将其写⼊⽂件,发送完成之后,服务端发数据告诉客户端发送完成,客户端核对⽂件信息,发送确认信息给服务端,关闭socket 链接。

由于篇幅,只贴⼏个⽅法的代码private void sendMsg(string srcPath, string dirPath, bool isUpdate, string fName, long fLength, long dLength, long dNumber){string msg = srcPath + "*" + dirPath + "*" + isUpdate + "*" + fName + "*" + fLength + "*" + dLength + "*" + dNumber;try{socket.Send(Encoding.UTF8.GetBytes(msg));}catch(Exception ex){throw new Exception("Send message error:\n " + ex);}}private void reciveFile(string srcPath, string dirPath,string fName,long dLength,long dReciveNumber,long dNumber){FileStream fs = null;try{try{fs = new FileStream(dirPath, FileMode.OpenOrCreate);string dir = "sendRes:OK:OK";sendDir(dir);}catch (Exception ex){string dire = "sendRes:error:" + ex.ToString();sendDir(dire);throw ex;}byte[] buffer = new byte[dLength];while (true){//Thread.Sleep(1);int n = socket.Receive(buffer);dReciveNumber++;fs.Write(buffer, 0, n);fs.Flush();if (dReciveNumber==dNumber){break;}}}catch (Exception ex){throw ex;}finally{if (fs != null){fs.Close(); }}}就到这⼉吧。

socket编程实例(文件传输)

socket编程实例(文件传输)

´ËʵÀýÊÇ¿Í»§¶ËÏò·þÎñÆ÷¶Ë´«ËÍÎļþ·þÎñÆ÷¶Ë´úÂëʵÏÖ£º#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <unistd.h>#include <arpa/inet.h>#include <errno.h>#include <fcntl.h>#define FU_SERVER_PORT 8080 /*set port*/#define FU_BUFFERSIZE 1024 /*set buffer size*/#define FU_LISTENQ 10 /*set listen max conncent*/int main(int argc,char *argv[]){int fu_listenfd,fu_connfd,fu_filefd; /*descriptor*/int fu_read,fu_write;int struct_size;struct sockaddr_in fu_servaddr,fu_cliaddr;char *fu_filename;char *p;char buffer[FU_BUFFERSIZE];fu_listenfd=socket(AF_INET,SOCK_STREAM,0); /*create socket*/if(fu_listenfd==-1){perror("fu_socket");exit(1);}memset(&fu_servaddr,0,sizeof(fu_servaddr)); /*servaddr set 0*/fu_servaddr.sin_family=AF_INET; /*init serveraddr*/fu_servaddr.sin_addr.s_addr=INADDR_ANY;fu_servaddr.sin_port=htons(FU_SERVER_PORT);/*bind fu_listenfd*/if(-1==(bind(fu_listenfd,(struct sockaddr *)&fu_servaddr, sizeof(fu_servaddr)))){exit(1);}/*listen fu_listenfd*/if(-1==(listen(fu_listenfd,FU_LISTENQ))){perror("fu_listen");exit(1);}/*file upload server start*/while(1){printf("file upload server starting......\n");memset(&fu_cliaddr,0,sizeof(fu_cliaddr));struct_size=sizeof(fu_cliaddr);fu_connfd=accept(fu_listenfd,(struct sockaddr *)&fu_cliaddr,&struct_size); if(-1==fu_connfd){perror("fu_accpet");continue;}fu_filename="/root/backup.txt";printf("will upload file name is:%s\n",fu_filename);fu_filefd=open(fu_filename,O_RDWR|O_CREAT|O_TRUNC,S_IRWXU);if (fu_filefd<0) {perror("open localhost file");continue;}while(fu_read=read(fu_connfd,buffer,FU_BUFFERSIZE)) {if (fu_read< 0) {perror("read client file");break;}if (-1==write(fu_filefd,buffer,fu_read)) {perror("writing to filefd error");break;}}if(-1==fu_read||-1==fu_write) continue;close(fu_filefd);printf("file upload success!\n");}close(fu_listenfd);return 0;}¿Í»§¶Ë´úÂëʵÏÖ£º#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>ar#include <sys/socket.h>#include <sys/stat.h>#include <unistd.h>#include <arpa/inet.h>#include <errno.h>#include <fcntl.h>#define FU_SERVER_PORT 8080 /*set port*/#define FU_BUFFERSIZE 1024 /*set buffer size*/int main(int argc,char *argv[]){int fu_sockfd,fu_filefd; /*descriptor*/int fu_read,fu_write;int struct_size;struct sockaddr_in fu_sockaddr;char *fu_filename;char *p;char buffer[FU_BUFFERSIZE];if (argc!=2) {perror("fu_Usage: <./client> <server IP>\n");exit(1);}fu_sockfd=socket(AF_INET,SOCK_STREAM,0); /*create socket*/if(fu_sockfd==-1){perror("fu_socket");exit(1);}memset(&fu_sockaddr,0,sizeof(fu_sockaddr)); /*servaddr set 0*/fu_sockaddr.sin_family=AF_INET; /*init serveraddr*/inet_aton(argv[1],&fu_sockaddr.sin_addr);fu_sockaddr.sin_port=htons(FU_SERVER_PORT);if(-1==(connect(fu_sockfd,(struct sockaddr *)&fu_sockaddr,sizeof(fu_sockaddr)))){ perror("fu_connect");exit(1);}printf("start connecting..........\n");fu_filename="./will.txt";printf("will upload file name is:%s\n",fu_filename);fu_filefd=open(fu_filename,O_RDONLY);if(-1==fu_filefd){perror("open will upload file");exit(1);}while(fu_read=read(fu_filefd,buffer,FU_BUFFERSIZE)){if(-1==fu_read){perror("read will upload file");exit(1);}p=buffer;while(fu_write=write(fu_sockfd,p,fu_read)){if(-1==fu_write){perror("write client file");break;}else if(fu_read==fu_write) break;else if(fu_write>0){p+=fu_write;fu_read-=fu_write;}}if(-1==fu_write) exit(1);}close(fu_filefd);close(fu_sockfd);printf("file already is uploaded!\n");}。

C#UDP(Socket)异步传输文件(1)

C#UDP(Socket)异步传输文件(1)

C#UDP(Socket)异步传输⽂件(1)⽤SCOKET 发送⽂件是⼀个不太好处理的问题,⽹上的例⼦也都是很简单的,我准备写⼀个⽐较完善的例⼦,这个就算是开始吧,以后的都会在这个例⼦的基础上进⾏修改,准备实现多线程传输、断点传输和⽂件传输的完备性检测。

在这个例⼦中,分别定义了⽂件发送管理类(SendFileManager),⽂件接收管理类(ReceiveFileManager),⽂件发送类(UdpSendFile)和⽂件接收类(UdpRecieveFile),以便实现尽量简单的就可以使⽤它们。

例⼦中的发送和读写⽂件都是基于异步的,实现了对⼤⽂件的分块发送。

例⼦中还提供了⼀个发送⽂件端和接收⽂件端,都是⽤前⾯的⼏个类实现了⽂件的发送和接受。

接受的⽂件默认放在接受⽂件端得根⽬录下,⽂件名以下划线开始。

下⾯是发送和接受⽂件的截图:SubmitSubmit上⼀篇⽂章中,实现了⽂件的基本传输,但是传输过程中的信息是看不到的,这⼀篇是对上⼀篇进⾏了⼀些改进,并且可以了解传输的信息(加⼊了Log),还加⼊了接收或者拒绝接收⽂件功能。

在上⼀篇中,⽂件发送类(UdpSendFile)和⽂件接收类(UdpRecieveFile)是直接⽤UdpClient来进⾏发送和接收的,现在,我添加了⼀个新的类UdpPeer,实现了基本的异步传输和接收数据的⽅法,定义了⼀个接⼝IDataCell作为⼀个数据发送单元,它包含两个⽅法:ToBuffer和FromBuffer,所有的发送数据都继承它来实现。

⽂件发送类(UdpSendFile)和⽂件接收类(UdpRecieveFile)中的UdpClient⽤UdpPeer代替了。

在⽂件发送类(UdpSendFile)和⽂件接收类(UdpRecieveFile)中加⼊了Log事件,以便于我们了解⽂件的传输过程,在⽂件接收类(UdpRecieveFile)中还加⼊了RequestSendFile事件,当接收到⼀个发送⽂件请求时可以同意或者拒绝接收⽂件。

C++利用SOCKET传送文件

C++利用SOCKET传送文件

C++利用SOCKET传送文件/*server.h*/#pragma comment(lib, "WS2_32")#include <WinSock2.h>#include <iostream>//#include <stdio.h>#include <assert.h>#ifndef COMMONDEF_H#define COMMONDEF_H#define MAX_PACKET_SIZE 10240 // 数据包的最大长度,单位是sizeof(char)#define MAXFILEDIRLENGTH 256 // 存放文件路径的最大长度#define PORT 4096 // 端口号#define SERVER_IP "127.0.0.1" // server端的IP地址// 各种消息的宏定义#define INVALID_MSG -1 // 无效的消息标识#define MSG_FILENAME 1 // 文件的名称#define MSG_FILELENGTH 2 // 传送文件的长度#define MSG_CLIENT_READY 3 // 客户端准备接收文件#define MSG_FILE 4 // 传送文件#define MSG_SENDFILESUCCESS 5 // 传送文件成功#define MSG_OPENFILE_ERROR 10 // 打开文件失败,可能是文件路径错误找不到文件等原因#define MSG_FILEALREADYEXIT_ERROR 11 // 要保存的文件已经存在了class CCSDef{public:#pragma pack(1) // 使结构体的数据按照1字节来对齐,省空间// 消息头struct TMSG_HEADER{char cMsgID; // 消息标识TMSG_HEADER(char MsgID = INVALID_MSG): cMsgID(MsgID){}};// 请求传送的文件名// 客户端传给服务器端的是全路径名称// 服务器传回给客户端的是文件名struct TMSG_FILENAME : public TMSG_HEADER{char szFileName[256]; // 保存文件名的字符数组TMSG_FILENAME(): TMSG_HEADER(MSG_FILENAME){}};// 传送文件长度struct TMSG_FILELENGTH : public TMSG_HEADER{long lLength;TMSG_FILELENGTH(long length): TMSG_HEADER(MSG_FILELENGTH), lLength(length){}};// Client端已经准备好了,要求Server端开始传送文件struct TMSG_CLIENT_READY : public TMSG_HEADER{TMSG_CLIENT_READY(): TMSG_HEADER(MSG_CLIENT_READY){}};// 传送文件struct TMSG_FILE : public TMSG_HEADER{union // 采用union保证了数据包的大小不大于MAX_PACKET_SIZE * sizeof(char) {char szBuff[MAX_PACKET_SIZE];struct{int nStart;int nSize;char szBuff[MAX_PACKET_SIZE - 2 * sizeof(int)];}tFile;};TMSG_FILE(): TMSG_HEADER(MSG_FILE){}};// 传送文件成功struct TMSG_SENDFILESUCCESS : public TMSG_HEADER{TMSG_SENDFILESUCCESS(): TMSG_HEADER(MSG_SENDFILESUCCESS){}};// 传送出错信息,包括:// MSG_OPENFILE_ERROR:打开文件失败// MSG_FILEALREADYEXIT_ERROR:要保存的文件已经存在了struct TMSG_ERROR_MSG : public TMSG_HEADER{TMSG_ERROR_MSG(char cErrorMsg): TMSG_HEADER(cErrorMsg){}};#pragma pack()};#endif/*server.cpp*/#include "server.h"char g_szNewFileName[MAXFILEDIRLENGTH];char g_szBuff[MAX_PACKET_SIZE + 1];long g_lLength;char* g_pBuff = NULL;// 初始化socket库bool InitSocket();// 关闭socket库bool CloseSocket();// 解析消息进行相应的处理bool ProcessMsg(SOCKET sClient);// 监听Client的消息void ListenToClient();// 打开文件bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient); // 传送文件bool SendFile(SOCKET sClient);// 读取文件进入缓冲区bool ReadFile(SOCKET sClient);int main(){InitSocket();ListenToClient();CloseSocket();return 0;}void ListenToClient(){// 创建socket套接字SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (SOCKET_ERROR == sListen){printf("Init Socket Error!\n");return;}// 绑定socket到一个本地地址sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.S_un.S_addr = INADDR_ANY;if (::bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR) {printf("Bind Error!\n");return;}// 设置socket进入监听状态if (::listen(sListen, 10) == SOCKET_ERROR){printf("Listen Error!\n");return;}printf("Listening To Client...\n");// 循环接收client端的连接请求sockaddr_in ClientAddr;int nAddrLen = sizeof(sockaddr_in);SOCKET sClient;while (INVALID_SOCKET == (sClient = ::accept(sListen, (sockaddr*)&ClientAddr, &nAddrLen))){}while (true == ProcessMsg(sClient)){}// 关闭同客户端的连接::closesocket(sClient);::closesocket(sListen);}bool InitSocket(){// 初始化socket dllWSADATA wsaData;WORD socketVersion = MAKEWORD(2, 2);if (::WSAStartup(socketVersion, &wsaData) != 0){printf("Init socket dll error\n");return false;}return true;}bool CloseSocket(){// 释放winsock库::WSACleanup();if (NULL != g_pBuff){delete [] g_pBuff;g_pBuff = NULL;}return true;}bool ProcessMsg(SOCKET sClient){int nRecv = ::recv(sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);if (nRecv > 0){g_szBuff[nRecv] = '\0';}// 解析命令CCSDef::TMSG_HEADER* pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff; switch (pMsgHeader->cMsgID){case MSG_FILENAME: // 文件名{OpenFile(pMsgHeader, sClient);}break;case MSG_CLIENT_READY: // 客户端准备好了,开始传送文件{SendFile(sClient);}break;case MSG_SENDFILESUCCESS: // 传送文件成功{printf("Send File Success!\n");return false;}break;case MSG_FILEALREADYEXIT_ERROR: // 要保存的文件已经存在了{printf("The file reay to send already exit!\n");return false;}break;}return true;}bool ReadFile(SOCKET sClient){if (NULL != g_pBuff){return true;}// 打开文件FILE *pFile;if (NULL == (pFile = fopen(g_szNewFileName, "rb"))) // 打开文件失败{printf("Cannot find the file, request the client input file name again\n"); CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_OPENFILE_ERROR);::send(sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);return false;}// 把文件的长度传回到client去fseek(pFile, 0, SEEK_END);g_lLength = ftell(pFile);printf("File Length = %d\n", g_lLength);CCSDef::TMSG_FILELENGTH tMsgFileLength(g_lLength);::send(sClient, (char*)(&tMsgFileLength), sizeof(CCSDef::TMSG_FILELENGTH), 0);// 处理文件全路径名,把文件名分解出来char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFname[_MAX_FNAME], szExt[_MAX_EXT];_splitpath(g_szNewFileName, szDrive, szDir, szFname, szExt);strcat(szFname,szExt);CCSDef::TMSG_FILENAME tMsgFileName;strcpy(tMsgFileName.szFileName, szFname);printf("Send File Name: %s\n", tMsgFileName.szFileName);::send(sClient, (char*)(&tMsgFileName), sizeof(CCSDef::TMSG_FILENAME), 0);// 分配缓冲区读取文件内容g_pBuff = new char[g_lLength + 1];if (NULL == g_pBuff){return false;}fseek(pFile, 0, SEEK_SET);fread(g_pBuff, sizeof(char), g_lLength, pFile);g_pBuff[g_lLength] = '\0';fclose(pFile);return true;}// 打开文件bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient){CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;// 对文件路径名进行一些处理char *p1, *p2;for (p1 = pRequestFilenameMsg->szFileName, p2 = g_szNewFileName;'\0' != *p1;++p1, ++p2){if ('\n' != *p1){*p2 = *p1;}if ('\\' == *p2){*(++p2) = '\\';}}*p2 = '\0';ReadFile(sClient);return true;}// 传送文件bool SendFile(SOCKET sClient){if (NULL == g_pBuff){ReadFile(sClient);}int nPacketBufferSize = MAX_PACKET_SIZE - 2 * sizeof(int); // 每个数据包存放文件的buffer大小// 如果文件的长度大于每个数据包所能传送的buffer长度那么就分块传送for (int i = 0; i < g_lLength; i += nPacketBufferSize){CCSDef::TMSG_FILE tMsgFile;tMsgFile.tFile.nStart = i;if (i + nPacketBufferSize + 1> g_lLength){tMsgFile.tFile.nSize = g_lLength - i;}else{tMsgFile.tFile.nSize = nPacketBufferSize;}//printf("start = %d, size = %d\n", tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);memcpy(tMsgFile.tFile.szBuff, g_pBuff + tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);::send(sClient, (char*)(&tMsgFile), sizeof(CCSDef::TMSG_FILE), 0);Sleep(0.5);}delete [] g_pBuff;g_pBuff = NULL;return true;}/*client.h同server.h*//*client.cpp*/#include "client.h"long g_lLength = 0;char* g_pBuff = NULL;char g_szFileName[MAXFILEDIRLENGTH];char g_szBuff[MAX_PACKET_SIZE + 1];SOCKET g_sClient;// 初始化socket库bool InitSocket();// 关闭socket库bool CloseSocket();// 把用户输入的文件路径传送到server端bool SendFileNameToServer();// 与server端连接bool ConectToServer();// 打开文件失败bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader);// 分配空间以便写入文件bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader); // 写入文件bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader);// 处理server端传送过来的消息bool ProcessMsg();int main(){InitSocket();ConectToServer();CloseSocket();return 0;}// 初始化socket库bool InitSocket(){// 初始化socket dllWSADATA wsaData;WORD socketVersion = MAKEWORD(2, 2);if (::WSAStartup(socketVersion, &wsaData) != 0){printf("Init socket dll error\n");exit(-1);}return true;}// 关闭socket库bool CloseSocket(){// 关闭套接字::closesocket(g_sClient);// 释放winsock库::WSACleanup();return true;}// 与server端连接进行文件的传输bool ConectToServer(){// 初始化socket套接字if (SOCKET_ERROR == (g_sClient = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))){printf("Init Socket Error!\n");exit(-1);}sockaddr_in servAddr;servAddr.sin_family = AF_INET;servAddr.sin_port = htons(PORT);servAddr.sin_addr.S_un.S_addr = ::inet_addr(SERVER_IP);if (INVALID_SOCKET == (::connect(g_sClient, (sockaddr*)&servAddr, sizeof(sockaddr_in)))){printf("Connect to Server Error!\n");exit(-1);}// 输入文件路径传输到server端SendFileNameToServer();// 接收server端传过来的信息,直到保存文件成功为止while (true == ProcessMsg()){}return true;}// 把用户输入的文件路径传送到server端bool SendFileNameToServer(){char szFileName[MAXFILEDIRLENGTH];printf("Input the File Directory: ");fgets(szFileName, MAXFILEDIRLENGTH, stdin);// 把文件路径发到server端CCSDef::TMSG_FILENAME tMsgRequestFileName;strcpy(tMsgRequestFileName.szFileName, szFileName);if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgRequestFileName), sizeof(CCSDef::TMSG_FILENAME), 0)){printf("Send File Name Error!\n");exit(-1);}return true;}// 处理server端传送过来的消息bool ProcessMsg(){CCSDef::TMSG_HEADER *pMsgHeader;int nRecv = ::recv(g_sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;switch (pMsgHeader->cMsgID){case MSG_OPENFILE_ERROR: // 打开文件错误{OpenFileError(pMsgHeader);}break;case MSG_FILELENGTH: // 文件的长度{if (0 == g_lLength){g_lLength = ((CCSDef::TMSG_FILELENGTH*)pMsgHeader)->lLength;printf("File Length: %d\n", g_lLength);}}break;case MSG_FILENAME: // 文件名{return AllocateMemoryForFile(pMsgHeader);}break;case MSG_FILE: // 传送文件,写入文件成功之后退出这个函数{if (WriteToFile(pMsgHeader)){return false;}}break;}return true;}// 打开文件失败bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader){if (NULL != g_pBuff)return true;assert(NULL != pMsgHeader);printf("Cannot find file!Please input again!\n");// 重新输入文件名称SendFileNameToServer();return true;}// 查找是否已经存在了要保存的文件,同时分配缓冲区保存文件bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader){assert(NULL != pMsgHeader);if (NULL != g_pBuff){return true;}CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;printf("File Name: %s\n", pRequestFilenameMsg->szFileName);// 把文件的路径设置为C盘根目录下strcpy(g_szFileName, "c:\\");strcat(g_szFileName, pRequestFilenameMsg->szFileName);// 查找相同文件名的文件是否已经存在,如果存在报错退出FILE* pFile;if (NULL != (pFile = fopen(g_szFileName, "r"))){// 文件已经存在,要求重新输入一个文件printf("The file already exist!\n");CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_FILEALREADYEXIT_ERROR);::send(g_sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);fclose(pFile);return false;}// 分配缓冲区开始接收文件,如果分配成功就给server端发送开始传送文件的要求g_pBuff = new char[g_lLength + 1];if (NULL != g_pBuff){memset(g_pBuff, '\0', g_lLength + 1);printf("Now ready to get the file %s!\n", pRequestFilenameMsg->szFileName); CCSDef::TMSG_CLIENT_READY tMsgClientReady;if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgClientReady), sizeof(CCSDef::TMSG_CLIENT_READY), 0)){printf("Send Error!\n");exit(-1);}}else{printf("Alloc memory for file error!\n");exit(-1);}return true;}// 写入文件bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader){assert(NULL != pMsgHeader);CCSDef::TMSG_FILE* pMsgFile = (CCSDef::TMSG_FILE*)pMsgHeader;int nStart = pMsgFile->tFile.nStart;int nSize = pMsgFile->tFile.nSize;memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);if (0 == nStart){printf("Saving file into buffer...\n");}memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);//printf("start = %d, size = %d\n", nStart, nSize);// 如果已经保存到缓冲区完毕就写入文件if (nStart + nSize >= g_lLength){printf("Writing to disk....\n");// 写入文件FILE* pFile;pFile = fopen(g_szFileName, "w+b");fwrite(g_pBuff, sizeof(char), g_lLength, pFile);delete [] g_pBuff;g_pBuff = NULL;fclose(pFile);// 保存文件成功传送消息给server退出serverCCSDef::TMSG_SENDFILESUCCESS tMsgSendFileSuccess;while (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgSendFileSuccess), sizeof(CCSDef::TMSG_SENDFILESUCCESS), 0)){}printf("Save the file %s success!\n", g_szFileName);return true;}else{return false;}}。

VCMFC下实现简单的socket发送接收文件

VCMFC下实现简单的socket发送接收文件

最简单的发送接收文件(VC6.0下编译通过):Server:#include<afx.h>#include<winsock2.h>#pragma comment(lib,"WS2_32.lib")int main(){WSADATA data;int m;WORD w=MAKEWORD(2,0);::WSAStartup(w,&data);SOCKET s,s1;s=::socket(AF_INET,SOCK_STREAM,0);//IPPROTO_TCP);sockaddr_in addr2,addr;char text[100]={0};int n=sizeof(addr2);addr.sin_family=AF_INET;addr.sin_port=htons(75);addr.sin_addr.S_un.S_addr=INADDR_ANY;::bind(s,(sockaddr *)&addr,sizeof(addr));::listen(s,5);printf("服务器已经启动\r\n");s1=::accept(s,(sockaddr*)&addr2,&n);if(s1!=NULL){printf("%s已经连接上\r\n",inet_ntoa(addr2.sin_addr));::recv(s1,text,100,0);//CFile file((LPSTR)text,CFile::modeReadWrite);if(text!=0){MessageBox(NULL,text,"xiaoxi",MB_OK);CFile file1(text,CFile::modeCreate|CFile::modeReadWrite);if(file1!=NULL){do{m=::recv(s1,text,100,0);file1.Write(text,100);}while(m==100);}file1.Close();}}::closesocket(s);::closesocket(s1);::WSACleanup();::WSACleanup();return 1;}Client:#include<afx.h>#include<winsock2.h>#pragma comment(lib,"WS2_32.lib")int main(){WSADATA data;WORD w=MAKEWORD(2,0);::WSAStartup(w,&data);SOCKET s;char text[100];char filename[100];printf("输入文件名:\n");gets(filename);CFile file(filename,CFile::modeReadWrite);CString str;s=::socket(AF_INET,SOCK_STREAM,0);sockaddr_in addr;addr.sin_family=AF_INET;addr.sin_port=htons(75);addr.sin_addr.S_un.S_addr=inet_addr("服务器IP");//本机程序服务器IP为你的机子IP或127.0.0.1;printf("客户端已经启动\r\n");int m=::connect(s,(sockaddr *)&addr,sizeof(addr));if(m!=-1){int m;str=file.GetFileName();MessageBox(NULL,str,"xiaoxi",MB_OK);::send(s,str,str.GetLength(),0);file.Read(text,100);do{::send(s,text,100,0);m=file.Read(text,100);printf("%d\n",m);}while(m);}file.Close();::closesocket(s);::WSACleanup();return 1;}有啥不明白的可以加群: 223048036,相互交流学习。

Linux下C语言socket通信实现发送读取的文件内容--简单实现代码

Linux下C语言socket通信实现发送读取的文件内容--简单实现代码

Linux下C语⾔socket通信实现发送读取的⽂件内容--简单实现代码本次代码涉及到的内容:socket通讯,⽂件读取读取的⽂件以及⽂件位置: 要读取的⽂件和c⽂件在同⼀个⽬录下。

客户端(client)读取的是123.xml,服务端(server)读取的是23.xml。

头⽂件( mysocket.h):1/* File Name: mysocket.h*/2 #include<stdio.h>3 #include<stdlib.h>4 #include<string.h>5 #include<errno.h>6 #include<sys/types.h>7 #include<sys/socket.h>8 #include<netinet/in.h>910/*11FunName:getFileAll12 Desc:get the file content13 Para:[fname] filename pointer14 Return:1.[*pBuf] file content pointer15 2.[*length] file length16*/17char *getFileAll(char *fname,int *length)18 {19int fileLight = 0;20char *pBuf; //定义⽂件指针21 FILE *pFile;2223 pFile = fopen(fname,"r"); //获取⽂件的指针24if(pFile == NULL)25 {26 printf("\nOpen file %s fail\n",pFile);27return NULL;28 }2930 fseek(pFile,0,SEEK_END); //把指针移动到⽂件的结尾,获取⽂件长度31 fileLight = ftell(pFile); //获取⽂件长度32 pBuf =(char *)malloc(fileLight);33 rewind(pFile); //把指针移动到⽂件开头因为我们⼀开始把指针移动到结尾,如果不移动回来会出错34 fread(pBuf,1,fileLight,pFile); //读⽂件35 pBuf[fileLight]=0; //把读到的⽂件最后⼀位写为0 要不然系统会⼀直寻找到0后才结束36 fclose(pFile); // 关闭⽂件37 *length = fileLight;38return pBuf;39 }服务端(cservice.c):1/* File Name: cservice.c */2 #include "mysocket.h"34#define DEFAULT_PORT 8000 //监听端⼝号5#define MAXLINE 409667int main(int argc, char** argv)8 {9int socket_fd, connect_fd;10int length; //file content Light11struct sockaddr_in servaddr;12char buff[4096];13int n;14char *p;15char *fname="./23.xml";16if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) //初始化Socket17 {18 printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);19 exit(0);20 }21//初始化22 memset(&servaddr, 0, sizeof(servaddr));23 servaddr.sin_family = AF_INET;24 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址设置成INADDR_ANY,让系统⾃动获取本机的IP地址。

socket完成文件传输的原理

socket完成文件传输的原理

socket完成文件传输的原理Socket通常被称作套接字,是应用程序与网络之间的接口,它能够使得程序能够通过网络与其他计算机进行通信。

在网络通信中,socket的作用十分重要,可以帮助我们在计算机之间实现信息交换,其中文件的传输也是socket的一个重要应用之一。

一、建立连接在使用socket进行文件传输之前,首先需要建立连接。

通常会有一个client端和一个server端,两者之间通过套接字连接。

建立连接比较简单,只需要指定好连接方式和端口号,然后进行连接就可以了。

连接成功之后,可以进行数据传输。

二、读写数据传输的过程中,client端需要将需要传输的文件抛给server端,server端将文件接收到之后就保存到本地磁盘中。

具体的实现过程需要使用读写操作完成。

在client端,首先需要打开需要传输的文件,然后使用read函数读取文件中的数据,并通过socket将数据传输给server端。

在传输的过程中,需要记录传输的字节数以及传输的总数据量,用于保证传输的完整性。

当读取到文件末尾时,数据传输结束,需要关闭文件和socket连接。

在server端,需要创建一个文件,并准备接收client端传输过来的数据。

在接收数据的过程中,使用write函数将接收到的数据写入到创建的文件中。

同样需要记录传输的数据字节数以及传输的总数据量,用于保证传输的完整性。

当接收的数据长度等于传输的总数据长度时,表示数据接收完毕,需要关闭socket连接和文件。

三、错误处理在文件传输的过程中,由于网络环境等原因,可能会出现一些错误,如传输中断、数据包丢失、连接断开等等。

需要及时处理这些错误,避免数据的丢失或者被篡改。

一般来说,在传输文件的过程中,可以设置超时功能,如果传输时间超过设定的时间,则认为传输失败,需要重新传输。

四、总结socket完成文件传输的原理很简单,主要分为连接建立、数据读写、错误处理三个步骤。

在实际应用中,需要考虑到很多因素,如网络环境、错误处理、带宽限制等等,但核心思路是不变的。

C#Socket传输大文件

C#Socket传输大文件

C#Socket传输⼤⽂件1.基础类TransferFiles,client和server都需要using System;using System.Collections.Generic;using System.Text;using ;using .Sockets;using System.Windows.Forms;namespace Server{public class TransferFiles{public static int SendData(Socket s, byte[] data){int total = 0;int size = data.Length;int dataleft = size;int sent;while (total < size){sent = s.Send(data, total, dataleft, SocketFlags.None);total += sent;dataleft -= sent;}return total;}public static byte[] ReceiveData(Socket s, int size){int total = 0;int dataleft = size;byte[] data = new byte[size];int recv;while (total < size){recv = s.Receive(data, total, dataleft, SocketFlags.None);if (recv == 0){data = null;break;}total += recv;dataleft -= recv;}return data;}public static int SendVarData(Socket s, byte[] data){int total = 0;int size = data.Length;int dataleft = size;int sent;byte[] datasize = new byte[4];try{datasize = BitConverter.GetBytes(size);sent = s.Send(datasize);while (total < size){sent = s.Send(data, total, dataleft, SocketFlags.None);total += sent;dataleft -= sent;}return total;}catch{return3;}}public static byte[] ReceiveVarData(Socket s){int total = 0;int recv;byte[] datasize = new byte[4];recv = s.Receive(datasize, 0, 4, SocketFlags.None);int size = BitConverter.ToInt32(datasize, 0);int dataleft = size;byte[] data = new byte[size];while (total < size){recv = s.Receive(data, total, dataleft, SocketFlags.None);if (recv == 0){data = null;break;}total += recv;dataleft -= recv;}return data;}}}2.Server端using System;using System.Collections.Generic;using System.Text;using ;using .Sockets;using System.Threading;using System.IO;using System.Configuration;namespace Server{public static class FileServer{private static Socket serverSocket;public static void Init(){//服务器IP地址IPAddress ip = IPAddress.Parse(ConfigurationManager.AppSettings["ListenIP"]);int myProt = Convert.ToInt32(ConfigurationManager.AppSettings["ListenFilePort"]);serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSocket.Bind(new IPEndPoint(ip, myProt)); //绑定IP地址:端⼝serverSocket.Listen(10); //设定最多10个排队连接请求Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString());//通过Clientsoket发送数据Thread myThread = new Thread(ListenClientConnect);myThread.Start();}public static void Exit(){serverSocket.Close();serverSocket = null;}private static void ListenClientConnect(){while (true){if (serverSocket != null){try{Socket clientSocket = serverSocket.Accept();Thread receiveThread = new Thread(Create);receiveThread.Start(clientSocket);}catch{break;}}}}public static void Create(object clientSocket){Socket client = clientSocket as Socket;//获得客户端节点对象IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;//获得[⽂件名]string SendFileName = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));//检查是否使⽤本地媒体库if (eLocal){//关闭套接字client.Close();return;}//获得[包的⼤⼩]string bagSize = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));//获得[包的总数量]int bagCount = int.Parse(System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client)));//获得[最后⼀个包的⼤⼩]string bagLast = System.Text.Encoding.Unicode.GetString(TransferFiles.ReceiveVarData(client));string fullPath = bine(Environment.CurrentDirectory,SendFileName);//创建⼀个新⽂件FileStream MyFileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write);//已发送包的个数int SendedCount = 0;while (true){byte[] data = TransferFiles.ReceiveVarData(client);if (data.Length == 0){break;}else{SendedCount++;//将接收到的数据包写⼊到⽂件流对象MyFileStream.Write(data, 0, data.Length);//显⽰已发送包的个数}}//关闭⽂件流MyFileStream.Close();//关闭套接字client.Close();SocketServer.pForm.ShowMessageBox(SendFileName + "接收完毕!");}}}3.Client端using System;using System.Collections.Generic;using System.Text;using System.IO;using ;using .Sockets;using System.Diagnostics;namespace Client{public static class FileClient{public static bool SendFile(string IP,int Port,string fullPath){//创建⼀个⽂件对象FileInfo EzoneFile = new FileInfo(fullPath);//打开⽂件流FileStream EzoneStream = EzoneFile.OpenRead();//包的⼤⼩int PacketSize = 10000;//包的数量int PacketCount = (int)(EzoneStream.Length / ((long)PacketSize));//最后⼀个包的⼤⼩int LastDataPacket = (int)(EzoneStream.Length - ((long)(PacketSize * PacketCount)));//指向远程服务端节点IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(IP), Port);//创建套接字Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//连接到发送端try{client.Connect(ipep);}catch{Debug.WriteLine("连接服务器失败!");return false;}//获得客户端节点对象IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;//发送[⽂件名]到客户端TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes());//发送[包的⼤⼩]到客户端TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(PacketSize.ToString()));//发送[包的总数量]到客户端TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(PacketCount.ToString()));//发送[最后⼀个包的⼤⼩]到客户端TransferFiles.SendVarData(client, System.Text.Encoding.Unicode.GetBytes(LastDataPacket.ToString()));bool isCut = false;//数据包byte[] data = new byte[PacketSize];//开始循环发送数据包for (int i = 0; i < PacketCount; i++){//从⽂件流读取数据并填充数据包EzoneStream.Read(data, 0, data.Length);//发送数据包if (TransferFiles.SendVarData(client, data) == 3){isCut = true;return false;break;}}//如果还有多余的数据包,则应该发送完毕!if (LastDataPacket != 0){data = new byte[LastDataPacket];EzoneStream.Read(data, 0, data.Length);TransferFiles.SendVarData(client, data);}//关闭套接字client.Close();//关闭⽂件流EzoneStream.Close();if (!isCut){return true;}return false;}}}。

C#socket传输文件

C#socket传输文件

查看文章c# socket 传输文件int port = 1234;int port = 1234;IPAddress ip = IPAddress.Parse("127.0.0.1");socket = newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); IPEndPoint iep = new IPEndPoint(ip,port);//socket.Blocking = false;socket.Bind(iep);socket.Listen(10);Console.WriteLine("start......");try{for (int i = 0; i < 10;i++ ){}}catch{Console.WriteLine("异常!");socket.Close();}接收端private void Receive(Socket socket){NetworkStream ns = new NetworkStream(socket);FileStream fs = new FileStream("c:\\file.txt", FileMode.OpenOrCreate); bool isRead = true;while (isRead){int count = ns.Read(this._receiveBuf, 0,this._receiveBuf.Length);int datanum = 0;datanum = BitConverter.ToInt32(this._receiveBuf, 0); //从buffer中的前4个字节读出countif (datanum > 0) //确定每次要接受多少字节数{fs.Write(this._receiveBuf, 4, datanum);}else //如果接受字节数为0 就推出{isRead = false;}}this.txtFile.Text = "文件传输成功";fs.Close();}---------------------发送端private void btSend_Click(object sender, System.EventArgs e){if (this._isConnect){_ns = _tc.GetStream();string path = this.txtPath.Text.Trim();FileStream fs = new FileStream(path, FileMode.Open);int sendCount = 0;byte[] countbuffer = null;byte[] clientbuffer = new byte[1004];while (sendCount < fs.Length && _ns.CanWrite){int count = fs.Read(_sendBuf, 0, _sendBuf.Length); //读出要发送的数据countbuffer = BitConverter.GetBytes(count);countbuffer.CopyTo(clientbuffer,0);_sendBuf.CopyTo(clientbuffer, 4);this._ns.Write(clientbuffer, 0, 4 + count); //写入网络流 sendCount += count;}countbuffer = BitConverter.GetBytes(0); //发送完文件后发送count = 0this._ns.Write(countbuffer, 0, countbuffer.Length); //使接收端停止_ns.Close();fs.Close();}}你为什么不把这两种方案结合在一起呢?首先把文件的总长度和每次发送的大小先发送出去,等接收端接受并分析,然后开始。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C++利用SOCKET传送文件/*server.h*/#pragma comment(lib, "WS2_32")#include <WinSock2.h>#include <iostream>//#include <stdio.h>#include <assert.h>#ifndef COMMONDEF_H#define COMMONDEF_H#define MAX_PACKET_SIZE 10240 // 数据包的最大长度,单位是sizeof(char)#define MAXFILEDIRLENGTH 256 // 存放文件路径的最大长度#define PORT 4096 // 端口号#define SERVER_IP "127.0.0.1" // server端的IP地址// 各种消息的宏定义#define INVALID_MSG -1 // 无效的消息标识#define MSG_FILENAME 1 // 文件的名称#define MSG_FILELENGTH 2 // 传送文件的长度#define MSG_CLIENT_READY 3 // 客户端准备接收文件#define MSG_FILE 4 // 传送文件#define MSG_SENDFILESUCCESS 5 // 传送文件成功#define MSG_OPENFILE_ERROR 10 // 打开文件失败,可能是文件路径错误找不到文件等原因#define MSG_FILEALREADYEXIT_ERROR 11 // 要保存的文件已经存在了class CCSDef{public:#pragma pack(1) // 使结构体的数据按照1字节来对齐,省空间// 消息头struct TMSG_HEADER{char cMsgID; // 消息标识TMSG_HEADER(char MsgID = INVALID_MSG): cMsgID(MsgID){}};// 请求传送的文件名// 客户端传给服务器端的是全路径名称// 服务器传回给客户端的是文件名struct TMSG_FILENAME : public TMSG_HEADER{char szFileName[256]; // 保存文件名的字符数组TMSG_FILENAME(): TMSG_HEADER(MSG_FILENAME){}};// 传送文件长度struct TMSG_FILELENGTH : public TMSG_HEADER{long lLength;TMSG_FILELENGTH(long length): TMSG_HEADER(MSG_FILELENGTH), lLength(length){}};// Client端已经准备好了,要求Server端开始传送文件struct TMSG_CLIENT_READY : public TMSG_HEADER{TMSG_CLIENT_READY(): TMSG_HEADER(MSG_CLIENT_READY){}};// 传送文件struct TMSG_FILE : public TMSG_HEADER{union // 采用union保证了数据包的大小不大于MAX_PACKET_SIZE * sizeof(char) {char szBuff[MAX_PACKET_SIZE];struct{int nStart;int nSize;char szBuff[MAX_PACKET_SIZE - 2 * sizeof(int)];}tFile;};TMSG_FILE(): TMSG_HEADER(MSG_FILE){}};// 传送文件成功struct TMSG_SENDFILESUCCESS : public TMSG_HEADER{TMSG_SENDFILESUCCESS(): TMSG_HEADER(MSG_SENDFILESUCCESS){}};// 传送出错信息,包括:// MSG_OPENFILE_ERROR:打开文件失败// MSG_FILEALREADYEXIT_ERROR:要保存的文件已经存在了struct TMSG_ERROR_MSG : public TMSG_HEADER{TMSG_ERROR_MSG(char cErrorMsg): TMSG_HEADER(cErrorMsg){}};#pragma pack()};#endif/*server.cpp*/#include "server.h"char g_szNewFileName[MAXFILEDIRLENGTH];char g_szBuff[MAX_PACKET_SIZE + 1];long g_lLength;char* g_pBuff = NULL;// 初始化socket库bool InitSocket();// 关闭socket库bool CloseSocket();// 解析消息进行相应的处理bool ProcessMsg(SOCKET sClient);// 监听Client的消息void ListenToClient();// 打开文件bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient); // 传送文件bool SendFile(SOCKET sClient);// 读取文件进入缓冲区bool ReadFile(SOCKET sClient);int main(){InitSocket();ListenToClient();CloseSocket();return 0;}void ListenToClient(){// 创建socket套接字SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (SOCKET_ERROR == sListen){printf("Init Socket Error!\n");return;}// 绑定socket到一个本地地址sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.S_un.S_addr = INADDR_ANY;if (::bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR) {printf("Bind Error!\n");return;}// 设置socket进入监听状态if (::listen(sListen, 10) == SOCKET_ERROR){printf("Listen Error!\n");return;}printf("Listening To Client...\n");// 循环接收client端的连接请求sockaddr_in ClientAddr;int nAddrLen = sizeof(sockaddr_in);SOCKET sClient;while (INVALID_SOCKET == (sClient = ::accept(sListen, (sockaddr*)&ClientAddr, &nAddrLen))){}while (true == ProcessMsg(sClient)){}// 关闭同客户端的连接::closesocket(sClient);::closesocket(sListen);}bool InitSocket(){// 初始化socket dllWSADATA wsaData;WORD socketVersion = MAKEWORD(2, 2);if (::WSAStartup(socketVersion, &wsaData) != 0){printf("Init socket dll error\n");return false;}return true;}bool CloseSocket(){// 释放winsock库::WSACleanup();if (NULL != g_pBuff){delete [] g_pBuff;g_pBuff = NULL;}return true;}bool ProcessMsg(SOCKET sClient){int nRecv = ::recv(sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);if (nRecv > 0){g_szBuff[nRecv] = '\0';}// 解析命令CCSDef::TMSG_HEADER* pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff; switch (pMsgHeader->cMsgID){case MSG_FILENAME: // 文件名{OpenFile(pMsgHeader, sClient);}break;case MSG_CLIENT_READY: // 客户端准备好了,开始传送文件{SendFile(sClient);}break;case MSG_SENDFILESUCCESS: // 传送文件成功{printf("Send File Success!\n");return false;}break;case MSG_FILEALREADYEXIT_ERROR: // 要保存的文件已经存在了{printf("The file reay to send already exit!\n");return false;}break;}return true;}bool ReadFile(SOCKET sClient){if (NULL != g_pBuff){return true;}// 打开文件FILE *pFile;if (NULL == (pFile = fopen(g_szNewFileName, "rb"))) // 打开文件失败{printf("Cannot find the file, request the client input file name again\n"); CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_OPENFILE_ERROR);::send(sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);return false;}// 把文件的长度传回到client去fseek(pFile, 0, SEEK_END);g_lLength = ftell(pFile);printf("File Length = %d\n", g_lLength);CCSDef::TMSG_FILELENGTH tMsgFileLength(g_lLength);::send(sClient, (char*)(&tMsgFileLength), sizeof(CCSDef::TMSG_FILELENGTH), 0);// 处理文件全路径名,把文件名分解出来char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFname[_MAX_FNAME], szExt[_MAX_EXT];_splitpath(g_szNewFileName, szDrive, szDir, szFname, szExt);strcat(szFname,szExt);CCSDef::TMSG_FILENAME tMsgFileName;strcpy(tMsgFileName.szFileName, szFname);printf("Send File Name: %s\n", tMsgFileName.szFileName);::send(sClient, (char*)(&tMsgFileName), sizeof(CCSDef::TMSG_FILENAME), 0);// 分配缓冲区读取文件内容g_pBuff = new char[g_lLength + 1];if (NULL == g_pBuff){return false;}fseek(pFile, 0, SEEK_SET);fread(g_pBuff, sizeof(char), g_lLength, pFile);g_pBuff[g_lLength] = '\0';fclose(pFile);return true;}// 打开文件bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient){CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;// 对文件路径名进行一些处理char *p1, *p2;for (p1 = pRequestFilenameMsg->szFileName, p2 = g_szNewFileName;'\0' != *p1;++p1, ++p2){if ('\n' != *p1){*p2 = *p1;}if ('\\' == *p2){*(++p2) = '\\';}}*p2 = '\0';ReadFile(sClient);return true;}// 传送文件bool SendFile(SOCKET sClient){if (NULL == g_pBuff){ReadFile(sClient);}int nPacketBufferSize = MAX_PACKET_SIZE - 2 * sizeof(int); // 每个数据包存放文件的buffer大小// 如果文件的长度大于每个数据包所能传送的buffer长度那么就分块传送for (int i = 0; i < g_lLength; i += nPacketBufferSize){CCSDef::TMSG_FILE tMsgFile;tMsgFile.tFile.nStart = i;if (i + nPacketBufferSize + 1> g_lLength){tMsgFile.tFile.nSize = g_lLength - i;}else{tMsgFile.tFile.nSize = nPacketBufferSize;}//printf("start = %d, size = %d\n", tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);memcpy(tMsgFile.tFile.szBuff, g_pBuff + tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);::send(sClient, (char*)(&tMsgFile), sizeof(CCSDef::TMSG_FILE), 0);Sleep(0.5);}delete [] g_pBuff;g_pBuff = NULL;return true;}/*client.h同server.h*//*client.cpp*/#include "client.h"long g_lLength = 0;char* g_pBuff = NULL;char g_szFileName[MAXFILEDIRLENGTH];char g_szBuff[MAX_PACKET_SIZE + 1];SOCKET g_sClient;// 初始化socket库bool InitSocket();// 关闭socket库bool CloseSocket();// 把用户输入的文件路径传送到server端bool SendFileNameToServer();// 与server端连接bool ConectToServer();// 打开文件失败bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader);// 分配空间以便写入文件bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader); // 写入文件bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader);// 处理server端传送过来的消息bool ProcessMsg();int main(){InitSocket();ConectToServer();CloseSocket();return 0;}// 初始化socket库bool InitSocket(){// 初始化socket dllWSADATA wsaData;WORD socketVersion = MAKEWORD(2, 2);if (::WSAStartup(socketVersion, &wsaData) != 0){printf("Init socket dll error\n");exit(-1);}return true;}// 关闭socket库bool CloseSocket(){// 关闭套接字::closesocket(g_sClient);// 释放winsock库::WSACleanup();return true;}// 与server端连接进行文件的传输bool ConectToServer(){// 初始化socket套接字if (SOCKET_ERROR == (g_sClient = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))){printf("Init Socket Error!\n");exit(-1);}sockaddr_in servAddr;servAddr.sin_family = AF_INET;servAddr.sin_port = htons(PORT);servAddr.sin_addr.S_un.S_addr = ::inet_addr(SERVER_IP);if (INVALID_SOCKET == (::connect(g_sClient, (sockaddr*)&servAddr, sizeof(sockaddr_in)))){printf("Connect to Server Error!\n");exit(-1);}// 输入文件路径传输到server端SendFileNameToServer();// 接收server端传过来的信息,直到保存文件成功为止while (true == ProcessMsg()){}return true;}// 把用户输入的文件路径传送到server端bool SendFileNameToServer(){char szFileName[MAXFILEDIRLENGTH];printf("Input the File Directory: ");fgets(szFileName, MAXFILEDIRLENGTH, stdin);// 把文件路径发到server端CCSDef::TMSG_FILENAME tMsgRequestFileName;strcpy(tMsgRequestFileName.szFileName, szFileName);if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgRequestFileName), sizeof(CCSDef::TMSG_FILENAME), 0)){printf("Send File Name Error!\n");exit(-1);}return true;}// 处理server端传送过来的消息bool ProcessMsg(){CCSDef::TMSG_HEADER *pMsgHeader;int nRecv = ::recv(g_sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;switch (pMsgHeader->cMsgID){case MSG_OPENFILE_ERROR: // 打开文件错误{OpenFileError(pMsgHeader);}break;case MSG_FILELENGTH: // 文件的长度{if (0 == g_lLength){g_lLength = ((CCSDef::TMSG_FILELENGTH*)pMsgHeader)->lLength;printf("File Length: %d\n", g_lLength);}}break;case MSG_FILENAME: // 文件名{return AllocateMemoryForFile(pMsgHeader);}break;case MSG_FILE: // 传送文件,写入文件成功之后退出这个函数{if (WriteToFile(pMsgHeader)){return false;}}break;}return true;}// 打开文件失败bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader){if (NULL != g_pBuff)return true;assert(NULL != pMsgHeader);printf("Cannot find file!Please input again!\n");// 重新输入文件名称SendFileNameToServer();return true;}// 查找是否已经存在了要保存的文件,同时分配缓冲区保存文件bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader){assert(NULL != pMsgHeader);if (NULL != g_pBuff){return true;}CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;printf("File Name: %s\n", pRequestFilenameMsg->szFileName);// 把文件的路径设置为C盘根目录下strcpy(g_szFileName, "c:\\");strcat(g_szFileName, pRequestFilenameMsg->szFileName);// 查找相同文件名的文件是否已经存在,如果存在报错退出FILE* pFile;if (NULL != (pFile = fopen(g_szFileName, "r"))){// 文件已经存在,要求重新输入一个文件printf("The file already exist!\n");CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_FILEALREADYEXIT_ERROR);::send(g_sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);fclose(pFile);return false;}// 分配缓冲区开始接收文件,如果分配成功就给server端发送开始传送文件的要求g_pBuff = new char[g_lLength + 1];if (NULL != g_pBuff){memset(g_pBuff, '\0', g_lLength + 1);printf("Now ready to get the file %s!\n", pRequestFilenameMsg->szFileName); CCSDef::TMSG_CLIENT_READY tMsgClientReady;if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgClientReady), sizeof(CCSDef::TMSG_CLIENT_READY), 0)){printf("Send Error!\n");exit(-1);}}else{printf("Alloc memory for file error!\n");exit(-1);}return true;}// 写入文件bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader){assert(NULL != pMsgHeader);CCSDef::TMSG_FILE* pMsgFile = (CCSDef::TMSG_FILE*)pMsgHeader;int nStart = pMsgFile->tFile.nStart;int nSize = pMsgFile->tFile.nSize;memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);if (0 == nStart){printf("Saving file into buffer...\n");}memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);//printf("start = %d, size = %d\n", nStart, nSize);// 如果已经保存到缓冲区完毕就写入文件if (nStart + nSize >= g_lLength){printf("Writing to disk....\n");// 写入文件FILE* pFile;pFile = fopen(g_szFileName, "w+b");fwrite(g_pBuff, sizeof(char), g_lLength, pFile);delete [] g_pBuff;g_pBuff = NULL;fclose(pFile);// 保存文件成功传送消息给server退出serverCCSDef::TMSG_SENDFILESUCCESS tMsgSendFileSuccess;while (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgSendFileSuccess), sizeof(CCSDef::TMSG_SENDFILESUCCESS), 0)){}printf("Save the file %s success!\n", g_szFileName);return true;}else{return false;}}。

相关文档
最新文档