Socket UDP远程传输图片:以Window系统为客户端,Ubuntu系统为服务端进行图片传输。
Window:客户端代码
#include
#include
#include
#include
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define Port 50001 // 服务器端口地址
#define IP_ADDRESS "192.168.1.101" // 服务器ip地址
// 图片包格式
struct Package
{
int length;
char data[1024];
int fin;
}picture;
int main(int argc, char* argv[])
{
WSADATA ws;
SOCKET clientSocket;
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
// 初始化Windows Socket
if(WSAStartup(MAKEWORD(2, 2), &ws) != 0)
{
printf("Init Windows Socket Failed! Error: %d\n", GetLastError());
return -1;
}
// 创建一个套接口
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
if(clientSocket == INVALID_SOCKET)
{
printf("Create Socket Failed! Error: %d\n", GetLastError());
return -1;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
addr.sin_port = htons(Port);
memset(addr.sin_zero, 0X00, 8); // 函数通常为新申请的内存做初始化工作
char img[20];
cout << "Please input img to send: ";
while(cin >> img)
{
// 打包发送图片
FILE *fp;
fp = fopen(img, "rb+");
fseek(fp, 0, SEEK_END);
int fend = ftell(fp);
fseek(fp, 0, 0);
int sendbytes, recvbytes;
while(fend > 0)
{
memset(picture.data, 0, sizeof(picture.data));
fread(picture.data, 1024, 1, fp);
if(fend >= 1024) //还有剩余包未发送完
{
picture.length = 1024;
picture.fin = 0;
}
else //最后一个包
{
picture.length = fend;
picture.fin = 1;
}
sendbytes = sendto(clientSocket, (char *)&picture, sizeof(struct Package), 0, (struct sockaddr*)&addr, addr_len);
if(sendbytes == SOCKET_ERROR)
{
printf("Send Picture Failed! Error:%d\n", GetLastError());
return -1;
}
else
{
fend -= 1024;
}
}
// 接收服务器回应
char recvbuffer[256];
recvbytes = recvfrom(clientSocket, recvbuffer, sizeof(recvbuffer), 0, (struct sockaddr*)&addr, &addr_len);
cout << "Server: " << recvbuffer << endl;
cout << "Please input img to send: ";
}
// 关闭socket
closesocket(clientSocket);
WSACleanup();
return 0;
}
Ubuntu:服务端代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define PORT 50001
struct Package
{
int length;
char data[1024];
int fin;
} picture;
//创建目录
void MakeDir(const string& filePath)
{
DIR *dp;
if((dp = opendir(filePath.c_str())) == NULL)
{
if(mkdir(filePath.c_str(), 0755) == -1)
cout << filePath << " build failed!" << endl;
}
closedir(dp);
}
/*初始化接收图像,并获取当前时间,以此存储命名图片*/
void initImage(FILE* &fp)
{
time_t t = time(0);
char imgpath[128];
strftime(imgpath, sizeof(imgpath), "%Y-%m-%d/", localtime(&t));
MakeDir(imgpath);
char imgname[64];
strftime(imgname, sizeof(imgname), "%Y%m%d%H%M%S.jpg", localtime(&t));
if(!(fp = fopen(strcat(imgpath, imgname), "wb+")))
{
printf("Open image Failed!\n");
exit(1);
}
}
int main(int argc, char* argv[])
{
struct sockaddr_in addr;
socklen_t sockfd, addr_len = sizeof(struct sockaddr_in);
/* 建立socket,注意必须是SOCK_DGRAM */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror ("socket failed!");
exit(1);
}
/* 填写sockaddr_in 结构 */
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
/* 绑定socket */
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr))<0)
{
perror("connect failed!");
exit(1);
}
while(1)
{
FILE* fp;
bool flag = true;
picture.fin = 0;
while(!picture.fin)
{
memset(picture.data, 0, sizeof(picture.data));
int recvbytes = recvfrom(sockfd, (char*)&picture, sizeof(struct Package),
0, (struct sockaddr *)&addr, &addr_len);
if(flag)
{
initImage(fp);
flag = false;
}
if(recvbytes == 0)
break;
fwrite(picture.data, picture.length, 1, fp);
}
/* 显示client端的网络地址和收到的字符串消息 */
//printf("Socket Server: IP: %s Connected!\n", inet_ntoa(addr.sin_addr));
cout << "Receive a picture. ip address: " << inet_ntoa(addr.sin_addr) << endl;
char sendbuffer[256] = "Server Response";
int sendbytes = sendto(sockfd, sendbuffer, sizeof(sendbuffer), 0, (struct sockaddr *)&addr, addr_len);
fclose(fp); /*关闭fp,刷新缓冲区*/
}
close(sockfd);
return 0;
}