C# 通过TCP套接字c发送二进制文件

C# 通过TCP套接字c发送二进制文件,c#,c++,c,sockets,tcp,C#,C++,C,Sockets,Tcp,我制作了一个客户端和服务器,通过套接字建立TCP连接,我试图通过套接字发送二进制数据,但我只能发送txt或pdf文件,我没有幸使用exe文件,我使用fread和fseek读取文件并将其拆分为缓冲区。当我读取整个exe文件时,它被成功发送,但当我分割它时,它被发送损坏 我读了一些关于插座的书,但我知道的还不多,我有一些问题 可以在一个send()中发送整个文件吗??或者我应该继续把它分成小块发送 还有,为什么exe文件在我成批发送时会损坏 谢谢大家! 客户端代码(c): int bufSize=1

我制作了一个客户端和服务器,通过套接字建立TCP连接,我试图通过套接字发送二进制数据,但我只能发送txt或pdf文件,我没有幸使用exe文件,我使用fread和fseek读取文件并将其拆分为缓冲区。当我读取整个exe文件时,它被成功发送,但当我分割它时,它被发送损坏

我读了一些关于插座的书,但我知道的还不多,我有一些问题

可以在一个send()中发送整个文件吗??或者我应该继续把它分成小块发送

还有,为什么exe文件在我成批发送时会损坏

谢谢大家!

客户端代码(c):

int bufSize=10000;
int sentBytes=0;
文件*pFile;
长剩余字节;
字符*缓冲区;
结果的大小;
pFile=fopen(“D:\\file.exe”、“rb”);
fseek(pFile,0,SEEK_END);
剩余字节数=ftell(pFile);
倒带(pFile);
int bufferSize=remainingBytes>bufSize?bufSize:剩余字节;
buffer=(char*)malloc(sizeof(char)*bufferSize);
发送(套接字,(字符*)和剩余字节,4,0);
而(剩余字节数>0)
{
fseek(pFile、sentBytes、SEEK_SET);
结果=fread(缓冲区,1,缓冲区大小,pFile);
if(bufferSize
服务器代码(用c#表示)

试试看
{
int bufferSize=200;
int len=0;
int receivedBytes=0;
整数剩余字节数=len;
字节[]长度=新字节[4];
//byte[]imgBuf=新字节[bufferSize];
int电流=0;
List coming=新列表();
插座[数量]。接收(长度,4,0);
len=位转换器.ToInt32(长度,0);
剩余字节数=len;
bufferSize=len缓冲区大小)
{
添加(新字节[bufferSize]);
//imgBuf=新字节[bufferSize];
套接字[number]。接收(即将到来的[current],缓冲区大小,0);
}
其他的
{
添加(新字节[remainingBytes]);
//imgBuf=新字节[剩余字节];
套接字[number]。接收(即将到来的[current],剩余字节,0);
bufferSize=remainingBytes;
}
remainingBytes-=缓冲区大小;
receivedBytes+=缓冲区大小;
电流++;
//Array.Clear(imgBuf,0,imgBuf.Length);
}
使用(var stream=newfilestream(@“C:\receivedFile.exe”,FileMode.Create))
{
使用(var binaryWriter=newbinarywriter(流))
{
foreach(字节[]缓冲区进入)
{
写入(缓冲区);
}
}
}
}
捕获(例外情况除外)
{this.setText(例如Message,textBox2);}
编辑:谢谢你的帮助,我成功了:)

试试看
{
int bufferSize=1024*100;
int len=0;
int receivedBytes=0;
整数剩余字节数=len;
int=0;
字节[]长度=新字节[4];
byte[]imgBuf=新字节[bufferSize];
int电流=0;
插座[数量]。接收(长度,4,0);
len=位转换器.ToInt32(长度,0);
剩余字节数=len;
bufferSize=len
您不会检查在
套接字[number]中实际接收的字节数。接收(即将到来的[current],bufferSize,0)。它不必等于您声明的缓冲区大小。

此外,如评论中所述,将整个文件保存在内存中不是一个好主意。

除了检查接收的字节数,还需要检查每个发送调用发送的字节数——如果TCP传输窗口已满,发送调用可能发送的数据比您请求的少,在这种情况下,您需要重新发送未发送的数据


通常,您总是需要检查系统调用的返回值,以检查可能发生的所有奇数角落情况。阅读send(2)和recv(2)的手册页,了解可能发生的所有事情的完整列表。

如果您要从文件系统传输整个文件,您可能应该使用(如果在Windows上)或(如果在Unix上)感谢您的回答,但正如我提到的,我在发送整个文件时一点问题也没有。问题只在我尝试将文件分块发送时出现。我想说的是,出于性能原因,无论文件是否分块,您都不应该首先通过在内存中缓冲来从磁盘发送文件-使用其中一个函数更有效。尝试过了,运气不好!还是sa
int bufSize = 10000;
int sentBytes = 0;


  FILE * pFile;
  long remainingBytes;
  char * buffer;
  size_t result;

  pFile = fopen ( "D:\\file.exe" , "rb" );
  fseek (pFile , 0 , SEEK_END);
  remainingBytes = ftell (pFile);
  rewind (pFile);

int bufferSize = remainingBytes > bufSize ? bufSize : remainingBytes;
buffer = (char*) malloc (sizeof(char)*bufferSize);
send(Socket, (char*)&remainingBytes, 4, 0);

while(remainingBytes > 0)
{
    fseek (pFile , sentBytes , SEEK_SET);
    result = fread(buffer,1,bufferSize,pFile);
    if(bufferSize < remainingBytes)
    {
        send(Socket, buffer, bufferSize, 0);
    }
    else
    {
        send(Socket, buffer, remainingBytes, 0);
        bufferSize = remainingBytes;
    }
    remainingBytes -= bufferSize;
    sentBytes += bufferSize;
}
        try
        {
            int bufferSize = 200;
            int len = 0;
            int receivedBytes = 0;
            int remainingBytes = len;
            byte[] length = new byte[4];
            //byte[] imgBuf = new byte[bufferSize];

            int current = 0;
            List<byte[]> coming = new List<byte[]>();

            sockets[number].Receive(length,4,0);

            len = BitConverter.ToInt32(length, 0);
            remainingBytes = len;

            bufferSize = len < bufferSize ? len : bufferSize;

            while(receivedBytes < len)
            {
                if (remainingBytes > bufferSize)
                {
                    coming.Add(new byte[bufferSize]);
                    //imgBuf = new byte[bufferSize];
                    sockets[number].Receive(coming[current], bufferSize, 0);
                }
                else
                {
                    coming.Add(new byte[remainingBytes]);
                    //imgBuf = new byte[remainingBytes];
                    sockets[number].Receive(coming[current], remainingBytes, 0);
                    bufferSize = remainingBytes;
                }
                remainingBytes -= bufferSize;
                receivedBytes += bufferSize;
                current++;
                //Array.Clear(imgBuf, 0, imgBuf.Length);
            }

            using (var stream = new FileStream(@"C:\receivedFile.exe",FileMode.Create))
            {
                using (var binaryWriter = new BinaryWriter(stream))
                {
                    foreach (byte[] buffer in coming)
                    {
                        binaryWriter.Write(buffer);
                    }
                }

            }
        }
        catch (Exception ex)
        { this.setText(ex.Message, textBox2); }
        try
        {
            int bufferSize = 1024 * 100;
            int len = 0;
            int receivedBytes = 0;
            int remainingBytes = len;
            int reached = 0;

            byte[] length = new byte[4];
            byte[] imgBuf = new byte[bufferSize];

            int current = 0;
            sockets[number].Receive(length,4,0);

            len = BitConverter.ToInt32(length, 0);
            remainingBytes = len;

            bufferSize = len < bufferSize ? len : bufferSize;
            imgBuf = new byte[len];

            while (reached < len)
            {
                reached += sockets[number].Receive(imgBuf, receivedBytes, remainingBytes, 0);
                remainingBytes = len - reached;
                receivedBytes = reached;
                current++;
                //Array.Clear(imgBuf, 0, imgBuf.Length);
            }

            using (var stream = new FileStream(@"C:\putty.exe",FileMode.Create))
            {
                using (var binaryWriter = new BinaryWriter(stream))
                {
                        binaryWriter.Write(imgBuf);
                }
            }
            Array.Clear(imgBuf, 0, imgBuf.Length);
        }
        catch (Exception ex)
        { this.setText(ex.Message, textBox2); }