windows下C++的socket编程入门--文件传输

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740632(v=vs.85).aspx

招着官方教程一步步做


主要函数或步骤:

  • WSAStartup, 初始化,WSACleanup,结束
  • socket(, ,) 构造函数,要有socket的instance才能实现传输
  • send() 
  • recv()
  • listen(), server端开始要监听自己的端口号有没有被连接
  • bind(),server的用来listen()的socket绑定address
  • accept(),如果没有client要连接,server在调用时就阻塞,有client要连接,就从这个要连接的队列里取出然后accept,然后server产生一个新的socket,而之前在listen()的socket是和这个不一样的,微软为何要弄两个socket出来呢,网上有一些解释,似乎是为了使用时更清楚一点


全部代码再后面可以直接找到

运行:先运行server的exe,再运行client的exe

这样就学会了基本的C/S传输

然后再加入文件操作:在server打开一个文件,从文件里读入内容,一个个包传过去,一直读到文件结束;在client创建一个用来接收传输内容的文件,一个个包接收过来,接收过来的内容写在这个文件里。

以下是我用官网代码修改后的文件传输系统

/*server.cpp*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <cstdio>

#pragma comment (lib, "Ws2_32.lib")

#define DEFAULT_PORT "27015"
#define DEFAULT_BUFLEN 512



int main ()
{
	int iResult, iSendResult;
	WSADATA wsaData;
	struct addrinfo *result = NULL, *ptr = NULL, hints;
	char temp[DEFAULT_BUFLEN];

	printf("input the file you want to transfer\n");
	scanf("%s", temp);
	//strcpy(temp, "input.txt");

	// open file 
	FILE * fp = fopen(temp, "rb"); // binary mode for read
	if(fp == NULL)
	{
		printf("open file %s failed\n", temp);
		return -1;
	}

	if(WSAStartup(MAKEWORD(2, 2), &wsaData))
	{
		printf("server WSAStartup failed: %d\n", iResult);
		return 1;
	}

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE; // caller to bind

	// resolve the local address and port to be used by user
	iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
	if(iResult != 0)
	{
		printf("server getaddrinfo faild: %d\n", iResult);
		WSACleanup();
		return 1;
	}
	
	// create a socket for server
	SOCKET ListenSocket = INVALID_SOCKET;
	ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if(ListenSocket == INVALID_SOCKET)
	{
		printf("server failed at socket(): %ld\n", WSAGetLastError());
		freeaddrinfo(result);
		WSACleanup();
		return 1;
	}

	// bind a socket
	iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
	if(iResult == SOCKET_ERROR)
	{
		printf("server bind faild: %ld\n", WSAGetLastError());
		freeaddrinfo(result);
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	freeaddrinfo(result); // once bind, no longer needed

	// listen on a socket
	if(listen(ListenSocket, SOMAXCONN))
	{
		printf("server listen socket failed %ld\n", WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	
	// accept a connection
	sockaddr_in client_addr;
	int nlen;
	SOCKET ClientSocket = INVALID_SOCKET;
	ClientSocket = accept(ListenSocket, NULL, NULL);
	if(ClientSocket == INVALID_SOCKET)
	{
		printf("server accept failed: %ld\n",WSAGetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	//char *ip = inet_ntoa(client_addr.sin_addr);
	//printf("establish connection to server %s\n", ip);

	// no longer need
	closesocket(ListenSocket);

	// file operation and send data
	
	int num = 0;
	while(!feof(fp))
	{
		num = fread(temp, 1, DEFAULT_BUFLEN, fp);
		send(ClientSocket, temp, num, 0);
	}
	printf("server file transfer success\n");
	
	fclose(fp);
	iResult = shutdown(ClientSocket, SD_SEND);
	if(iResult == SOCKET_ERROR)
	{
		printf("server shutdown failed %ld\n", WSAGetLastError());
		closesocket(ClientSocket);
		WSACleanup();
		return 1;
	}
	closesocket(ClientSocket);
	WSACleanup();

	return 0;
}

/*client.cpp*/

//prevent winsock.h (version 1.1)from being included by windows.h
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h> // after winsock2.h
#include <cstdio>

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#define DEFAULT_PORT "27015"
#define DEFAULT_BUFLEN 512




int main ()
{
	int iResult;
	WSADATA wsaData;
	struct addrinfo *result = NULL, *ptr = NULL, hints;
	char sendbuf[] = "this is a test for client";
	char recvbuf[DEFAULT_BUFLEN];
	int recvbuflen = DEFAULT_BUFLEN;
	char temp[DEFAULT_BUFLEN], file_name[DEFAULT_BUFLEN];

	printf("input ip address of server and file name\n");
	scanf("%s%s", temp, file_name);

	//create file
	FILE *fp = fopen(file_name, "wb");
	if(fp == NULL)
	{
		printf("create file %s failed\n", file_name);
		return -1;
	}

	// initialize
	if(WSAStartup(MAKEWORD(2,2), &wsaData))
	{
		printf("client WSAStartup failed: %d\n", iResult);
		return 1;
	}

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	// resolve the server address and port, argv[1] is server name
	iResult = getaddrinfo(temp, DEFAULT_PORT, &hints, &result);
	if(iResult != 0)
	{
		printf("client get addrinfor fail: %d\n", iResult);
		WSACleanup(); // terminate use of WS2_32.dll
		return 1;
	}

	
	SOCKET ConnectSocket = INVALID_SOCKET;
	for(ptr = result; ptr != NULL; ptr = ptr->ai_next)
	{
		// create a socket for client
		ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
		if(ConnectSocket == INVALID_SOCKET)
		{
			printf("client socket failed with error %ld\n", WSAGetLastError());
			WSACleanup();
			return 1;
		}

		// connect to server
		iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
		if(iResult == SOCKET_ERROR)
		{
			closesocket(ConnectSocket);
			ConnectSocket = INVALID_SOCKET;// if fail try next address returned by getaddrinfo
			continue;
		}
		break;
	}

	
	freeaddrinfo(result);
	if(ConnectSocket == INVALID_SOCKET)
	{
		printf("client unable to connect to server\n");
		WSACleanup();
		return 1;
	}
	
	//receive data from server
	int num = 0;
	while (1)
	{
		num = recv(ConnectSocket, temp, DEFAULT_BUFLEN, 0);
		if(num == 0) 
			break;
		fwrite(temp, 1, num, fp);
	}
	printf("transmission done\n");

	fclose(fp);
	closesocket(ConnectSocket);
	WSACleanup();

	return 0;
}

另:看到一个比较高端的,也可以参考下

http://blog.csdn.net/maopig/article/details/6801166?ADUIN=460174867&ADSESSION=1389244225&ADTAG=CLIENT.QQ.5275_.0&ADPUBNO=26274





你可能感兴趣的:(windows下C++的socket编程入门--文件传输)