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" ...
随机推荐
- OS X El Capitan的 U 盘制作过程
本文并非最终版本,如有更新或更正会第一时间置顶,联系方式详见文末 如果觉得本文内容过长,请前往本人 “简书” 0.在 AppStore 下载 OS X El Capitan AppStore ...
- tomcat服务器奇异事件
我在A电脑里面启动服务器,服务器里面之前上传了XX文件,然后在A电脑浏览器能访问到(但是修改无效),在B电脑也能访问到(修改有效果),现在我把A电脑里面的文件删除,在A电脑都能访问到但是修改不了文件, ...
- RecyclerView item 状态错乱
adapter中: private List<Integer> checkboxUserIdList = new ArrayList<>(); 在如下这个方法中: public ...
- js 无缝滚动效果学习
<!DOCTYPE html> <html> <head> <title>无缝滚动测试</title> <meta http-equi ...
- 解决使用osgModeling的Loft生成管子时的bug(续)
今天发现有一些情况下, 还是无法生成管道, 排查了一天发现问题好像出在管线头两个点的x完全相同时, 会出这个问题. 看了半天的Loft源码, 发现问题出在Loft::considerBasisX函 ...
- sql server 权限体系
--给sql server添加一个新用户[账号,密码,数据库名] execute sp_addlogin 'baishi', '123','db'; execute sp_addlogin 'wx ...
- showModalDialog 刷新问题,在页面中跳转问题
showModalDialog 刷新问题 ,在页面中跳转问题 <html><head> <base target="_self" >< ...
- wifi 破解
基础的知识: ESSID :无线网络的名字 BSSID :是AP的mac地址 CH: 工作信道 AP :无线访问接入点 WEP WPA/WPA2 STATION :客户机mac DHCP ...
- 函数Curry化
之前写过一个函数Curry化的小文章 那会儿对Curry化的理解不够深,平时遇到的需要Curry化的例子也比较少,今天,重新整理这个问题 函数Curry化,其实就是将一个参数非常多的函数,在大多数参数 ...
- 被swoole坑哭的PHP程序员
被swoole坑哭的PHP程序员 2015-09-16 09:57 文帅营 博客园 字号:T | T 首先说一下对swoole的理解:披着PHP外衣的C程序.很多PHPer朋友看到swoole提供的强 ...