c/s架构的网络通讯程序:功能包括拨号,发消息,传文件

功能描述:

客户端:

1.拨号,输入IP,连接服务器

2.可以选择接收文件

(1)等待服务器的发送

(2)接收待传文件的名称

(3)是否修改该文件的名称

(4)在该客户端的文件夹下查看传送的文件

3.可以选择发送消息,发送“exit”即告诉服务器停止发送消息

4.停止通讯

服务器端:

扫描二维码关注公众号,回复: 5092476 查看本文章

1.显示连接客户端的IP和端口号

2.接收传文件命令

(1)输入想传送的文件名(相对路径和绝对路径都行)

(2)等待客户端的准备好

(3)传送文件

3.接收发送消息的命令,遇到“exit”即关闭该功能

4.停止通讯

note:

(1)发送消息的功能并没有实现聊天的功能。传文件和发消息都是单向的。可以进一步修改。

(2)由于采用二进制读写文件,所以可以传输任意类型,不受格式的限制,如.txt,.mp3,.mp4,.pptx,...都可以

prompt:以下代码环境为VS2015,不同环境请适当修改。传文件采用结尾加了标志位,0代表文件还在传送,1代表已经出传送完毕,需要控制缓冲区的长度,来加报头,去报头。


Sever代码:

// server.cpp : 定义控制台应用程序的入口点。
//

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#endif
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <cstdio>
#include <io.h>
#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];
	char file_name[DEFAULT_BUFLEN];

	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed with error: %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 server address and port
	iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
	if (iResult != 0) {
		printf("getaddrinfo failed with error: %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);


	sockaddr_in clientAddr;
	int addrlen = sizeof(clientAddr);
	ClientSocket = accept(ListenSocket, (sockaddr*)&clientAddr, &addrlen);


	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);

	printf("Connect a client\nShow client ip and socket:%s, %d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
	while (1) {
		while (1) {
			iResult = recv(ClientSocket, temp, DEFAULT_BUFLEN, 0);
			if (iResult > 0) {
				temp[iResult] = '\0';
				printf("\n%s command received.\n\n", temp);
				break;
			}
		}

		if (strcmp(temp, "file") == 0) {
			// file operation and send data
			printf("input the file you want to transfer\n");
			scanf_s("%s", temp, DEFAULT_BUFLEN);
			FILE * fp;
			errno_t err;
			err = fopen_s(&fp, temp, "rb"); // binary mode for read

			if (err != 0)
			{
				printf("open file %s failed\n", temp);
				return -1;
			}

			while (1) {
				if (send(ClientSocket, temp, (int)strlen(temp), 0) > 0) {
					printf("Wait the client to prepare well...\n");
					break;
				}
				//Sleep(1000);
			}

			memset(temp, 0, DEFAULT_BUFLEN);
			while (1) {
				iResult = recv(ClientSocket, temp, DEFAULT_BUFLEN, 0);
				if (iResult > 0 && strcmp(temp,"ok") == 0) {
					printf("the client is well ready to receive the file\n");
					break;
				}
			}

			memset(temp, 0, DEFAULT_BUFLEN);
			int length = 0;
			while (1)
			{
				length = fread(temp, sizeof(char), DEFAULT_BUFLEN - 1, fp);
				if (length == 0) {
					temp[length] = '1';//end flag is '1'
					if (send(ClientSocket, temp, length + 1, 0) < 0)
					{
						printf("Send File: %s Failed\n");
						break;
					}
					break;
				} else {
					temp[length] = '0';
					if (send(ClientSocket, temp, length + 1, 0) < 0)
					{
						printf("Send File: %s Failed\n");
						break;
					}
					memset(temp, 0, DEFAULT_BUFLEN);
				}
			}
			fclose(fp);
			printf("server file transfer success\n");
		}
		else if (strcmp(temp, "message") == 0) {
			while (1) {
				memset(temp, 0, DEFAULT_BUFLEN);
				iResult = recv(ClientSocket, temp, SOMAXCONN, 0);
				if (iResult > 0) {

					temp[iResult] = '\0';
					if (strcmp(temp, "exit") == 0) {
						break;
					}
					else
						printf("Receive data:%s\n", temp);
					memset(temp, 0, DEFAULT_BUFLEN);
				}
			}
		}
		else if (strcmp(temp, "exit") == 0) {
			printf("the client is disconnected\n");
			break;
		}
	}

	if (iResult == SOCKET_ERROR)
	{
		printf("server shutdown failed %ld\n", WSAGetLastError());
		closesocket(ClientSocket);
		WSACleanup();
		return 1;
	}
	while (1);
	closesocket(ClientSocket);
	WSACleanup();

	return 0;
}


client代码:

// 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>
#include<iostream>
#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\n");
	scanf_s("%s", temp, DEFAULT_BUFLEN);

	// Initialize Winsock
	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
	if (iResult != 0) {
		printf("WSAStartup failed with error: %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;
	}
	while (1) {
		//temp[DEFAULT_BUFLEN];
		printf("\nPlease input a command to run:1.\"file\" 2.\"message\" 3.\"exit\"\n");
		std::cin >> temp;
		iResult = send(ConnectSocket, temp, (int)strlen(temp), 0);
		if (iResult <= 0) {
			printf("The command is unuseful.\n");
		}

		if (strcmp(temp, "file") == 0) {
			printf("Wait a file from server...\n");
			//create file
			FILE * fp;
			errno_t err;

			while (1) {
				iResult = recv(ConnectSocket, file_name, DEFAULT_BUFLEN, 0);
				if (iResult > 0)
					break;
			}

			file_name[iResult] = '\0';

			//receive data from server
			printf("\nprepare to receive :\n%s\n\n",file_name);
			printf("Do you want to change the received file name and position:\n1.yes 2.no\n");
			char input[100];
			scanf_s("%s", input, 100);
			if (strcmp(input,"yes") == 0) {
				scanf_s("%s", file_name, DEFAULT_BUFLEN);
			}			


			err = fopen_s(&fp, file_name, "wb+"); // binary mode for read
			if (err != 0)
			{
				printf("open file %s failed\n", file_name);
				return -1;
			}

	
			while (1) {
				if (send(ConnectSocket, "ok", (int)strlen("ok"), 0) > 0) {
					printf("ready to receive the file...\n");
					break;
				}
					
			}

			memset(temp, 0, DEFAULT_BUFLEN);
			int length = 0;

			while ((length = recv(ConnectSocket, temp, DEFAULT_BUFLEN, 0)) > 0)
			{
				if (temp[length-1] == '1') {//识别文件的结尾
					break;
				}

				if (fwrite(temp, sizeof(char), length - 1, fp) < length - 1)
				{
					printf("File: %s Write Failed\n", file_name);
					break;
				}
				memset(temp, 0, DEFAULT_BUFLEN);
			}
			printf("transmission done\n");
			fclose(fp);
		}
		else if (strcmp(temp, "message") == 0) {
			printf("\nIntput the \"exit\" to end the transformation.\n");
			while (1) {
				printf("input your message:\n");
				std::cin >> temp;

				if (strcmp(temp, "exit") == 0) {
					iResult = send(ConnectSocket, temp, (int)strlen(temp), 0);
					break;
				}

				iResult = send(ConnectSocket, temp, (int)strlen(temp), 0);
				if (iResult <= 0) {
					printf("The command is unuseful.\n");
				}
			}

		}
		else if (strcmp(temp, "exit") == 0) {
			printf("The transformation is over.\n");
			break;
		}
	}

	while (1);
	closesocket(ConnectSocket);
	WSACleanup();

	return 0;
}



猜你喜欢

转载自blog.csdn.net/weixin_40597170/article/details/78635991