udp文件傳輸源碼
㈠ 誰能給我一個基於DUP協議的可靠數據傳輸的源代碼
如何用vb的winsocket解決udp文件傳送丟包的問題
udp協議是1種無連接的協議,他和tcp協議比較有傳輸速度快,佔用資源少的問題。
但是由於udp協議本身沒有自動找包的功能,因此經常會出現丟包的現象,會造成傳送的文件丟包的現象
因為時間匆忙和水平有限,本人在效率上沒有作優化,只是簡單的實現,請大家自己看源碼吧
注釋:
主要功能:把文件猜成4k大小的包 在包頭+上包的長度 接受了1個包判斷長度是否和接受的長度相符如果
符合那麼就繼續發,如果出現丟包那麼就從發
希望大家有什麼好的建議通知我,我會盡量完善的
Option Explicit
'==============================================
'===============================
'udp傳文件
'客戶端
'作者: 影子
'================================
'==============================================
Dim FileNumber As Integer '用來存文件的句柄
Dim LenFile As Long '文件的長度
Private Sub Command2_Click()
closefile
End Sub
Private Sub Form_Load()
Winsock0.LocalPort = 5698
Winsock0.Bind
beginfile
End Sub
Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)
Dim FileByte() As Byte
Winsock0.GetData FileByte, vbArray + vbByte '接收類型為:位元組數組
Dim mendByte() As Byte, i As Long, j As Long
Dim temp As String, temp1 As String
'獲得包長
j = UBound(FileByte)
'合並包頭
For i = 0 To 7 Step 2
temp = temp & Chr(FileByte(i))
Next
'比較長度看丟包沒有
If Val(temp) = j Then
ReDim mendByte(j - 8)
' 提出包頭
For i = 0 To j - 8
mendByte(i) = FileByte(i + 7)
Next
' 寫文件
Put #FileNumber, , mendByte
' 發送繼續發送的請求
frmmain.Winsock0.SendData "ok"
Else
'出現丟包,請求重發
frmmain.Winsock0.SendData "no"
End If
End Sub
Public Sub beginfile()
FileNumber = FreeFile '取得未使用的文件號
Open "c:\aaa.exe" For Binary As #FileNumber '打開文件
End Sub
Public Sub closefile() '關閉文件句柄
Close #FileNumber
End Sub
Option Explicit
Dim GetFileNum As Integer
Dim LenFile As Long
Dim Sendbaye() As Byte '發送的包
'===============================
'udp傳文件
'作者: 影子
'伺服器端
'================================
Private Sub Command1_Click()
GetFileNum = FreeFile '取得未使用的文件號
LenFile = FileLen("d:\aa.rar") '獲得需傳送的文件的長度
Open "d:\aa.rar" For Binary As #GetFileNum '打開需傳送的文件
Command1.Enabled = False
' 傳送文件
Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile)
Text1.Text = Now
End Sub
Private Sub Form_Load()
frmmain.Winsock0.RemoteHost = "192.168.0.12" '伺服器ip
frmmain.Winsock0.RemotePort = 5698
End Sub
'=========================================================================
'為了清晰,下面分別用兩個子過程來完成計算這次還可以傳多少個位元組的數據和傳送數據
'==========================================================================
Private Function SplitFile() As Long '拆包
On Error Resume Next
Dim GetCount As Long
'計算出這次可發送的位元組數
If LenFile >= 4000 Then
GetCount = 4000
LenFile = LenFile - GetCount
Else
GetCount = LenFile
LenFile = LenFile - GetCount
End If
SplitFile = GetCount
End Function
Private Sub TCPSendFile(objWinSock As Winsock, FileNumber As Integer, SendLen As Long)
Dim FileByte() As Byte, i As Long, j As Long
Dim temp As String
ReDim Sendbaye(0)
Dim tempa As String * 4
ReDim FileByte(SendLen - 1)
tempa = SendLen + 7
Sendbaye = tempa ' 把長度負值給包頭
Get #FileNumber, , FileByte '讀取文件
ReDim Preserve Sendbaye(SendLen + 7) '把包頭+到文件頭
For i = 0 To UBound(FileByte)
Sendbaye(i + 7) = FileByte(i)
Next
frmmain.Winsock0.SendData Sendbaye
End Sub
Private Sub Winsock0_DataArrival(ByVal bytesTotal As Long)
Dim str As String
frmmain.Winsock0.GetData str
Select Case str
Case "ok"
'成功繼續發送
If LenFile = 0 Then '發送完成
MsgBox "成功"
Exit Sub
End If
Call TCPSendFile(frmmain.Winsock0, GetFileNum, SplitFile)
Case "no"
'不成功重發上一個包
frmmain.Winsock0.SendData Sendbaye
End Select
End Sub
㈡ C語言 UDP文件傳輸
void ThreadReceive(PVOID param)
{
static struct sockaddr_in server; // 綁定地址
static SOCKET ListenSocket; // 等待接收數據的socket
char buf[4096];
int len = sizeof(client);
int result;
ListenSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ListenSocket == INVALID_SOCKET)
{
perror("opening stream socket");
exit(0);
}
server.sin_family = PF_INET;
server.sin_addr.s_addr = htonl( INADDR_ANY ); // 任何地址
server.sin_port = htons(LOCAL_PORT);
if (SOCKET_ERROR == bind(ListenSocket, (struct sockaddr *)&server, sizeof(server)) )
{
printf("Error: 綁定失敗\n");
exit(1);
closesocket( ListenSocket );
}
printf("socket port %d \n", ntohs(server.sin_port));
while(TRUE)
{
//接收數據
result = recvfrom(ListenSocket, buf, sizeof(buf)-1, 0, (struct sockaddr *)&client, &len);
if ( result > 0 )
{
buf[result] = 0;
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
}
}
closesocket(ListenSocket);
}
㈢ 求一個UDP套接字文件傳輸的C/C++代碼
你的問題是一個偽命題!
如果不用TCP/IP協議,自己寫底層協議的話,基本上不可實現:
1)你需要編寫驅動網卡的驅動程序---涉及操作系統內核編程;
2)你需要定義自己的應用協議模塊,該模塊調用網卡驅動,從頭造輪子,屬於重復工作,在現在來說,基本沒什麼意義!
㈣ 請教用C語言編的藉助UDP協議實現的文件傳輸的程序
server代碼
#include<sys/socket.h>;
#include<string.h>;
#include<netinet/in.h>;
#include<stdio.h>;
#include<stdlib.h>;
#include<fcntl.h>;
#include<sys/stat.h>;
#include<unistd.h>;
#include<errno.h>;
#include<sys/select.h>;
#include<sys/time.h>;
#include<unistd.h>;
#include<sys/types.h>;
#define SERV_PORT 2500
#define MAX_SIZE 1024*40
void recvUDP(char name[20],int sockfd)
{
int ret,fd;
mode_t fdmode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
char mesg[MAX_SIZE];
fd_set rdset;
struct timeval tv;
int rlen,wlen;
int i;
fd = open(name,O_RDWR|O_CREAT|O_APPEND,fdmode);
if(fd == -1)
{
printf("open file %s error:%n",name,strerror(errno));
exit(-1);
}
for(i=0;;i++)
{
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&rdset);
FD_SET(sockfd,&rdset);
ret = select(sockfd+1,&rdset,NULL,NULL,&tv);
if(ret == -1)
{
printf("select error %s\n",strerror(errno));
exit(-1);
}
else if(ret==0)
{
printf("select timeout,continue circle\n");
continue;
}
if(FD_ISSET(sockfd,&rdset))
{
memset(mesg,0,MAX_SIZE);
rlen = read(sockfd,mesg,MAX_SIZE);
if(rlen <=0 )
{
printf("read error %s\n",strerror(errno));
exit(-1);
}
if(!strcmp(mesg,"end"))
{
printf("recv end.\n");
break;
}
wlen = write(fd,mesg,rlen);
if(wlen != rlen )
{
printf("write error %s\n",strerror(errno));
exit(-1);
}
}
printf("The %d times write\n",i);
}
close(fd);
}
int main(int argc, char *argv[])
{
int sockfd;
int r;
struct sockaddr_in servaddr;
sockfd = socket(AF_INET,SOCK_DGRAM,0); /*create a socket*/
/*init servaddr*/
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
/*bind address and port to socket*/
if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) == -1)
{
perror("bind error");
exit(-1);
}
r = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);
recvUDP(argv[1],sockfd);
return 0;
}
client代碼
#include<sys/types.h>;
#include<sys/socket.h>;
#include<string.h>;
#include<netinet/in.h>;
#include<stdio.h>;
#include<stdlib.h>;
#include<arpa/inet.h>;
#include<fcntl.h>;
#include<sys/stat.h>;
#include<errno.h>;
#include<sys/sysinfo.h>;
#include<sys/select.h>;
#include<sys/time.h>;
#include<unistd.h>;
#define MAX_SIZE 1024*40
#define SERV_PORT 2500
void connectUDP(char name[20],int sockfd,struct sockaddr *pservaddr,socklen_t servlen)
{
char buf[MAX_SIZE];
fd_set wrset;
struct timeval tv;
int rlen,wlen;
int fd;
int ret;
int i;
if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)
{
perror("connet error");
exit(1);
}
else
printf("connect server ok!\n");
fd = open(name,O_RDONLY);
if(fd==-1)
{
printf("fopen error %s\n",strerror(errno));
exit(-1);
}
i=0;
while(1)
{
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&wrset);
FD_SET(sockfd,&wrset);
ret = select(sockfd+1,NULL,&wrset,NULL,&tv);
if(ret == -1)
{
printf("select error %s\n",strerror(errno));
exit(-1);
}
else if(ret==0)
{
printf("select timeout,continue circle\n");
continue;
}
memset(buf,0,MAX_SIZE);
if(FD_ISSET(sockfd,&wrset))
{
rlen = read(fd,buf,MAX_SIZE);
if(rlen <0)
{
printf("fread data error %s\n",strerror(errno));
exit(-1);
}
else if(rlen==0)
{
wlen = write(sockfd,"end",3);
if(wlen !=3)
{
printf("write end error\n",strerror(errno));
exit(-1);
}
printf("all complete\n");
close(fd);
close(sockfd);
exit(0);
}
wlen = write(sockfd,buf,rlen);
if(wlen != rlen)
{
printf("write data to sockfd error:%s\n",strerror(errno));
exit(-1);
}
i++;
usleep(500);
printf("The %d times read\n",i);
}
}
}
int main(int argc ,char *argv[])
{
char *fh;
struct sysinfo s_info;
float time1,time2;
int error1,error2;
int sockfd;
struct stat fsize;
struct sockaddr_in servaddr;
error1= sysinfo(&s_info);
time1 = s_info.uptime;
int r;
if(argc != 3)
{
printf("useage:udpclient<IPaddress>;\n");
exit(1);
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_port = htons(SERV_PORT);
if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0)
{
printf("[%s]is not a valid IPaddress\n",argv[1]);
exit(1);
}
fh = argv[2];
sockfd =socket(AF_INET,SOCK_DGRAM,0);
r = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);
connectUDP(argv[2],sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
fprintf(stderr,"ServerIP:\t%s\n",argv[1]);
if(stat(argv[2],&fsize) == -1)
perror("failed to get fiel statusi\n");
else
fprintf(stderr,"file name:\t%s\nfile size:\t%dK\n",argv[2],fsize.st_size/1024);
error2=sysinfo(&s_info);
time2 = s_info.uptime;
printf("tranfice file time =%fs\n",(time2-time1));
}
makefile
all:send recv
send:send.c
gcc -Wall send.c -o send
recv:recv.c
gcc -Wall recv.c -o recv
clean:
rm -rf send recv
㈤ 請教用C語言編的藉助UDP協議實現的文件傳輸的程序
本程序在 Windows 7 Visual Studio 2015 和 linux Ubuntu 15.04 GCC 5.11 下均編譯運行測試通過。
本程序支持 Windows 和 Linux 之間傳送文件,如果要在 Windows 和 Linux 之間傳送文件,文件名不能出現中文。
本程序支持無線 WiFi,支持 USB 收發器,但僅支持區域網內傳送文件,傳送文件需要輸入對方的 IP 地址。
本程序包括伺服器端和客戶端,既可以發送文件又可以接收文件。如果要在同一台機器上測試需要同時打開兩個程序。
Windows 下查看本機 IP 地址的命令是:
ipconfig
Linux 下查看本機 IP 地址的命令是:
ifconfig
以下是程序代碼:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#ifdef_MSC_VER
#include<winsock2.h>
#include<windows.h>
#pragmacomment(lib,"ws2_32.lib")
#else
#include<pthread.h>
#include<unistd.h>
#include<signal.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#endif
//存放發送接收字元數組大小
#defineSIZEA65501
//每次發送接收位元組數
#defineSIZEB65500
typedefstructsockaddr_inSockAddrIn;
SockAddrInserverAddr,remoteAddr,clientAddr;
//埠號
intiServerPort,iClientPort;
//新建socket信息
intiUDP;
//字元串轉整型
intstrToInt(char*acStr)
{
inti,iIndex=0,iNum=0,iSize=0;
if(acStr[0]=='+'||acStr[0]=='-')
iIndex=1;
for(iSize=iIndex;;iSize++)
if(acStr[iSize]<'0'||acStr[iSize]>'9')
break;
for(i=iIndex;i<iSize;i++)
iNum+=(int)pow(10,iSize-i-1)*(acStr[i]-48);
if(acStr[0]=='-')
iNum=-iNum;
returniNum;
}
//整型轉字元串
voidintToStr(intiInt,char*acStr)
{
intiIndex=0,iSize,iNum,iBit,i,j;
if(iInt<0)
{
acStr[0]='-';
iInt=-iInt;
iIndex=1;
}
for(i=0;;i++)
if(iInt<pow(10,i))
break;
iSize=i;
for(i=0;i<iSize;i++)
{
iNum=pow(10,iSize-i-1);
iBit=iInt/iNum;
iInt-=iNum*iBit;
acStr[i+iIndex]=iBit+48;
}
if(iSize!=0)
acStr[iSize+iIndex]='