Windows下通过socket进行字符串和文件传输
今天在windows平台下,通过socket实现了简单的文件传输。通过实现这一功能,了解基本的windows网络编程和相关函数的使用方法。
在windows平台上进行网络编程,首先都需要调用函数WSAStartup()进行链接库的初始化。如果没有使用该函数进行初始化,则后面会出现10093的错误(可以通过GetLastError()获得错误码)。
进行初始化后,客户端和服务器进行不同的工作。但是不管是服务器还是客户端,都需要用到两个最基本的结构体,分别是SOCKET和sockaddr_in。其中,SOCKET结构体用于表示一个socket连接。sockaddr_in表示一个地址结构,用它来保存需要连接的主机ip地址及端口号,或者是需要监听的端口号。
客户端基本流程图如下图:
服务器基本流程图如下:
这次实现的功能主要是:客户端向服务器发送一个字符串和一个文件(图片文件),服务器以接收到的字符串为文件名,并将接收到的文件保存到本地。
客户端源代码如下:
//file_transfer.h /**************************************************
*Author:xiongmao
*
*Date:2016/2/22 17:53
*
*Description:用于网络间的文件传输
*
**************************************************/ #pragma once
#include <string> #ifndef WIN_SOCKET_
#define WIN_SOCKET_
#include <WinSock2.h>
#pragma comment(lib , "ws2_32.lib")
#endif using std::string; class FileTransfer
{
public:
FileTransfer();
~FileTransfer();
/*****************************************************************************
* @name : setIpAndPort
*
* @author : xiongmao
*
* @create date : 2016/2/18 16:04
*
* @function:设置目标ip地址和端口号
*
* @inparam :
* ip:目标ip地址
* port:目标端口号
* @outparam :
*
* @last change : 2016/2/18 16:04
*****************************************************************************/
bool setIpAndPort(string ip,int port);
/*****************************************************************************
* @name : setFilePath
*
* @author : xiongmao
*
* @create date : 2016/2/18 16:06
*
* @function:设置需要发送的文件的路径
*
* @inparam :
* path:文件路径
* @outparam :
*
* @last change : 2016/2/18 16:06
*****************************************************************************/
bool setFilePath(string path);
/*****************************************************************************
* @name : sendFile
*
* @author : xiongmao
*
* @create date : 2016/2/18 16:07
*
* @function:发送简单字符串信息和指定文件给目标主机
*
* @inparam :
* msg:需要发送给目标主机的一些简单信息
* filePath:需要传输的文件的路径
* @outparam :
*
* @last change : 2016/2/21 16:41
*****************************************************************************/
bool sendFile(string msg,string filePath);
private: const static int BUFFER_SIZE=; int m_Port;
string m_IpAddr;
string m_FilePath; WSADATA ws;
SOCKET m_ServerSocket;
sockaddr_in m_ServerAddr; };
//file_transfer.cpp #include "file_transfer.h"
#include <fstream>
#include <iostream>
using namespace std; FileTransfer::FileTransfer()
{
m_Port=-;
/*
if ( WSAStartup(MAKEWORD(2,2), &ws) != 0 )
{
printf("Init Windows Socket Failed,the error code is : %d \n", GetLastError());
exit(-1);
}
*/
} FileTransfer::~FileTransfer()
{
WSACleanup();
} bool FileTransfer::setIpAndPort(string ip,int port)
{
m_IpAddr=ip;
m_Port=port;
m_ServerAddr.sin_family = AF_INET;
m_ServerAddr.sin_addr.s_addr = inet_addr(m_IpAddr.c_str());
m_ServerAddr.sin_port = htons(m_Port);
return true;
} bool FileTransfer::setFilePath(string path)
{
fstream testFile;
testFile.open(path,ios::in);
if(!testFile)
{
printf("file not exist!\n");
return false;
}
m_FilePath=path;
return true;
} bool FileTransfer::sendFile(string msg,string filePath)
{
m_FilePath=filePath;
m_ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( m_ServerSocket == INVALID_SOCKET )
{
printf("Create Socket Failed::%d\n", GetLastError());
return false;
}
if (connect(m_ServerSocket,(LPSOCKADDR)& m_ServerAddr,sizeof(m_ServerAddr))==SOCKET_ERROR)
{
printf("can not connect to server! NO: %d\n",GetLastError());
return false;
}
FILE * fp =fopen(m_FilePath.c_str(),"rb");
if (fp ==NULL)
{
printf("file open error!");
return false;
}
char buffer[BUFFER_SIZE];
//发送文件名(在卡口中用来发送识别出来的车牌号)
memset(buffer,,BUFFER_SIZE);
strncpy(buffer,msg.c_str(),msg.length());
if(send(m_ServerSocket,buffer,msg.length(),)<)
{
printf("seng msg fail!(the error num is : %d )\n",GetLastError());
return false;
}
//发送文件数据
memset(buffer,,sizeof(buffer));
int length = ;
while ((length = fread(buffer, sizeof(char), sizeof(buffer), fp)) > )
{
if (send(m_ServerSocket, buffer, length, )== SOCKET_ERROR)
{
printf("Send File: %s Failed\n", m_FilePath.c_str());
printf("error num : %d\n",GetLastError());
return false;
}
memset(buffer, , sizeof(buffer));
}
fclose(fp);
closesocket(m_ServerSocket);
return true;
}
客户端测试主函数
//main.cpp /*************************************************************************
> File Name: Win_Server.c
> Author: SongLee
************************************************************************/ #include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "file_transfer.h"
using namespace std; #define PORT 8087
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
#pragma comment(lib, "WS2_32") int main()
{
while()
{
bool flag;
string filename;
printf("input file name:");
cin>>filename;
FileTransfer ft;
ft.setIpAndPort(SERVER_IP,PORT);
ft.setFilePath(filename);
flag=ft.sendFile(filename,filename);
if (flag)
{
printf("send file %s success \n",filename.c_str());
}
else
{
printf("send file %d fail.The error code is : %d \n",GetLastError());
}
}
system("pause");
return ;
}
服务器测试代码
//main.cpp /*************************************************************************
> 服务器测试代码
> 先从客户端接收一个字符串,作为文件的文件名,接着接收客户端发送过来的文
> 件并保存至本地
************************************************************************/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <WinSock2.h> #define PORT 8087
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024
#pragma comment(lib, "WS2_32") int main()
{
// 声明并初始化一个服务端(本地)的地址结构
sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT); // 初始化socket dll
WSADATA wsaData;
WORD socketVersion = MAKEWORD(, );
if(WSAStartup(socketVersion, &wsaData) != )
{
printf("Init socket dll error!");
exit();
} // 创建socket
SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, );
if (SOCKET_ERROR == m_Socket)
{
printf("Create Socket Error!");
exit();
} //绑定socket和服务端(本地)地址
if (SOCKET_ERROR == bind(m_Socket, (LPSOCKADDR)&server_addr, sizeof(server_addr)))
{
printf("Server Bind Failed: %d", WSAGetLastError());
exit();
} //监听
if (SOCKET_ERROR == listen(m_Socket, ))
{
printf("Server Listen Failed: %d", WSAGetLastError());
exit();
} while (true)
{
printf("wait for file transfer...\n");
char file_name[BUFFER_SIZE];
char buffer[BUFFER_SIZE]; sockaddr_in client_addr;
int client_addr_len = sizeof(client_addr);
//首先接收发送过来的字符串
SOCKET m_New_Socket = accept( m_Socket, (sockaddr *)&client_addr, &client_addr_len);
if (SOCKET_ERROR == m_New_Socket)
{
printf("Server Accept Failed: %d", WSAGetLastError());
break;
}
memset(buffer,,sizeof(buffer));
memset(file_name,,sizeof(file_name));
if (recv(m_New_Socket,buffer,sizeof(buffer),)<)
{
printf("recv file name fail!\n");
continue;
}
strncpy(file_name,buffer,strlen(buffer));
printf("recv file name : %s \n",file_name);
FILE * fp = fopen(file_name,"wb");
if (fp==NULL)
{
printf("open file error\n");
continue;
}
//获取字符串后继续获取文件数据
memset(buffer, , BUFFER_SIZE);
int length = ;
while ((length = recv(m_New_Socket, buffer, BUFFER_SIZE, )) > )
{
if (fwrite(buffer, sizeof(char), length, fp) < length)
{
printf("File: %s Write Failed\n", file_name);
break;
}
memset(buffer, , BUFFER_SIZE);
}
fclose(fp);
printf("file transfer success!\n");
}
system("pause");
return ;
}
在进行编程的过程中,自己有以下几个问题没弄懂:
(1)connect函数函数是怎么知道连接请求是否产生错误了?
(2)当一次connect()连接成功后,如何主动关闭这个socket连接,直接调用closesocket函数就可以了吗?
Windows下通过socket进行字符串和文件传输的更多相关文章
- windows下的socket网络编程
windows下的socket网络编程 windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了, ...
- windows下的socket网络编程(入门级)
windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先 ...
- winsock教程- windows下的socket编程(c语言实现)
winsock教程- windows下的socket编程(c语言实现) 使用winsock进行socket 编程 这是一个学习windows下socket编程(c语言)的快速指南.这是因为一下 ...
- Windows下Git Bash中VIM打开文件中文乱码
Windows下Git Bash中VIM打开文件中文乱码,解决方法是: 步骤一 admin@DESKTOP-O99620V MINGW64 /d/项目GGE/Hard_for_GGE (master) ...
- 一个简单的Windows下的socket程序
服务器端代码server.cpp: #include <stdio.h> #include <WinSock2.h> #pragma comment(lib,"ws2 ...
- Linux下TCP网络编程与基于Windows下C#socket编程间通信
一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...
- Linux和windows下内核socket优化项 (转)
问题: No buffer space available Linux: vi /etc/sysctl.conf net.core.netdev_max_backlog = 30000 每个网络接口 ...
- linux 批量替换文件内容及查找某目录下所有包含某字符串的文件
转载请注明来源:https://www.cnblogs.com/hookjc/ 1. sed C代码 grep -rl matchstring somedir/ | xargs sed -i 's ...
- windows下安装easy_install, pip 及whl文件安装方法
转:http://www.cnblogs.com/wu-wenmin/p/4250330.html 写在前面的话 最近在看"Computer Vision with Python" ...
随机推荐
- 逗号分割符--字段中含逗号等情况的解析方法Java实现
最近在处理文本字符串时,没一行数据都是按照逗号分割的,每个字段值一般情况是带有双引号的,但是有的字段值里面还包含逗号,甚至有的字段就没有双引号,这个分割起来就有点麻烦了 下面说一下我解决方法,如果谁有 ...
- 分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)
本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用( ...
- linux中grep命令详解
http://jingyan.baidu.com/article/76a7e409e72777fc3b6e158a.html
- CodeForces 279D The Minimum Number of Variables 题解
题目大意: 有一组n个不相同的数字组成数串:a1,a2,a3-an. 1.一个数组b. 2.第一个操作我们将b0的值赋为a1.之后我们有n-1个操作,第k次操作我们将by=bi+bj(y,i,j可能相 ...
- Leetcode Merge Intervals
Given a collection of intervals, merge all overlapping intervals. For example,Given [1,3],[2,6],[8,1 ...
- linux shell trap的使用
原文地址:http://blog.sina.com.cn/s/blog_62eb16bb01014dbh.html 一. trap捕捉到信号之后,可以有三种反应方式: (1)执行一段程序来处理这一信号 ...
- 2016huasacm暑假集训训练四 数论_A
题目链接:http://acm.hust.edu.cn/vjudge/contest/125308#problem/F 题意:狼捉兔子,兔子躲在n个洞中一个,这n个洞围成一个圈,狼会从第0号洞开始,搜 ...
- HDU 1166 敌兵布阵(分块)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- 关于BeanUiles.copyPropertis()的用法
最近的项目遇到BeanUiles.copyPropertis(),大大的简化了代码量.用hibernate从数据库中映射的实体类,与pojo对象进行转换,传统做法 Object obj = baseD ...
- mysql快速导出数据库ER图和数据字典(附navicat11安装教程及资源)
♣ mysql使用navicat11快速导出数据库ER图 ♣ mysql使用navicat11快速导出数据库数据字典 ♣ navicat11 for mysql (这里是mysql5.7.12)专业版 ...