功能描述:
客户端:
1.拨号,输入IP,连接服务器
2.可以选择接收文件
(1)等待服务器的发送
(2)接收待传文件的名称
(3)是否修改该文件的名称
(4)在该客户端的文件夹下查看传送的文件
3.可以选择发送消息,发送“exit”即告诉服务器停止发送消息
4.停止通讯
服务器端:
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.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;
}