是否可以在两个系统中使用tcp / ip协议运行客户端服务器通信? [英] Is it possible to run client server communication using tcp/ip protocol in two systems?

查看:109
本文介绍了是否可以在两个系统中使用tcp / ip协议运行客户端服务器通信?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我想知道是否可以在两个不同的系统中运行服务器和客户端通信。一个充当服务器而另一个充当客户端?



服务器将数据发送到客户端,客户端应该读取它。



服务器代码:



Hi,

I would like to know is it possible to run server and client communication in two different systems. One acting as a server and the other acting as client?

With the server sending data to the client and the client should read it.

Server code:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

  int main()
{
  int welcomeSocket, newSocket;
  char buffer[1024];
  struct sockaddr_in serverAddr;
  struct sockaddr_storage serverStorage;
  socklen_t addr_size;

  /*---- Create the socket. The three arguments are: ----*/
  /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
  welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);

  /*---- Configure settings of the server address struct ----*/
  /* Address family = Internet */
  serverAddr.sin_family = AF_INET;
  /* Set port number, using htons function to use proper byte order */
  serverAddr.sin_port = htons(6777);
  /* Set IP address to localhost */
  serverAddr.sin_addr.s_addr = INADDR_ANY;
  /* Set all bits of the padding field to 0 */
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

  /*---- Bind the address struct to the socket ----*/
  bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

  /*---- Listen on the socket, with 5 max connection requests queued ----*/
  if(listen(welcomeSocket,5)==0)
    printf("Listening\n");
  else
    printf("Error\n");

  /*---- Accept call creates a new socket for the incoming connection ----*/
  addr_size = sizeof serverStorage;
  newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);

  /*---- Send message to the socket of the incoming connection ----*/
  strcpy(buffer,"Hello World \n");
  send(newSocket,buffer,13,0);

  return 0;
}







客户代码:






Client Code:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main()

{

  int clientSocket;
  char buffer[1024];
  struct sockaddr_in serverAddr;
  socklen_t addr_size;

  /*---- Create the socket. The three arguments are: ----*/
  /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
  clientSocket = socket(PF_INET, SOCK_STREAM, 0);

  /*---- Configure settings of the server address struct ----*/
  /* Address family = Internet */
  serverAddr.sin_family = AF_INET;
  /* Set port number, using htons function to use proper byte order */
  serverAddr.sin_port = htons(6777);
  /* Set IP address to localhost */
  serverAddr.sin_addr.s_addr = INADDR_ANY;
  /* Set all bits of the padding field to 0 */
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);

  /*---- Connect the socket to the server using the address struct ----*/
  addr_size = sizeof serverAddr;
  connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

  /*---- Read the message from the server into the buffer ----*/
  recv(clientSocket, buffer, 1024, 0);

  /*---- Print the received message ----*/
  printf("Data received: %s",buffer);

  return 0;

}

推荐答案

错误在于寻址。

服务器行:

The error is in the addressing.
While in the server the line:
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = INADDR_ANY;



无论如何都要工作,因为IP堆栈将所有传入连接从任何本地端口路由到侦听套接字,这在客户端是错误的。 />
在这种情况下,客户端正在尝试连接到没有服务器的本地计算机,因为它位于不同的计算机上。

所以同时拥有服务器和客户端机器工作,因为伪地址LOCALHOST是相同的,所以两个程序可以互相交谈。

但是当服务器和客户端停留在不同的机器上时,这是一个错误!

要制作它的工作原理你必须在客户端代码中指定真实的服务器地址。

即如果服务器地址是192.168.1.23,则必须以这种方式对客户端程序进行编码:


Works anyway because the IP stack routes all incoming connections from any of local ports to the listening socket, this is an error on the client side.
The client in this case is trying to connect to the local machine where there is no server, because it is on a different machine.
So having both server and client on the same machine works because the pseudoaddress LOCALHOST is the same so the two programs can talk each other.
But when server and client stay on different machines this is an error!
To make it work you have to specify the real server address in the client code.
I.e. if the server address is 192.168.1.23 you have to code the client program this way:

/* Set server IP address to real server address in client code */
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.23");


数据,变量大小和其他所有内容都非常混乱...

你有从某个地方剪切并粘贴代码,几乎盲目地修改它。特别是你已经放大了所有可能的东西,缓冲区,大小等等。你已经在堆栈上分配了许多Mb的缓冲区...

为了使它工作,取代例程:

- 在客户端:

There is a very big mess in data, variables size and all the rest...
You have cut and paste the code from somewhere modifying it almost blindly. In particular you have enlarged everything you could, buffers, sizes and so on. You have allocated buffers of many Mb on the stack...
To make it work replace the routines:
- in the client:
int receive_audio(long long int socket)
{

	long int buffersize = 0, recv_size = 0, size = 0, read_size, write_size;

	char verify = '1';

	FILE *audio;

	//Find the size of the audio
	recv(socket, (char *)&size, sizeof(int), 0);

	//Send our verification signal
	send(socket, &verify, sizeof(char), 0);

	//Make sure that the size is bigger than 0
	if (size <= 0)
	{
		printf("Error has occurred. Size less than or equal to 0 \n");
		return -1;
	}

	audio = fopen("/home/sosdt009/Desktop/received.mp3", "w");

	if (audio == NULL)
	{
		printf("Error has occurred. audio file could not be opened \n");
		return -1;
	}

	//Loop while we have not received the entire file yet

	while (recv_size < size)
	{
		ioctl(socket, FIONREAD, &buffersize);

		//We check to see if there is data to be read from the socket 
		if (buffersize > 0)
		{
			char *pBuf = malloc(buffersize);
			if (!pBuf)
			{
				fprintf(stderr, "Memory Error. Cannot allocate!\n");
				exit(-1);
			}

			read_size = recv(socket, pBuf, buffersize, 0);
			if (read_size  < 0)
			{
				printf("%s", strerror(errno));
			}

			//Write the currently read data into our audio file
			write_size = fwrite(pBuf, 1, buffersize, audio);

			free(pBuf);

			//Increment the total number of bytes read
			recv_size += read_size;
		}
	}

	fclose(audio);
	printf("audio successfully Received! \n");
	return 1;
}





- 在服务器中:



- In the server:

int send_audio(long long int socket)
{

	FILE *audio;
	long int size, read_size, stat, packet_index;
	char send_buffer[512], read_buffer[512];
	packet_index = 1;

	audio = fopen("/home/sosdt009/Desktop/ROBO.mp3", "r");

	if (audio == NULL)
	{
		printf("Error Opening audio File");
		exit(-1);
	}

	printf("Getting audio Size\n");

	fseek(audio, 0, SEEK_END);
	size = ftell(audio);
	fseek(audio, 0, SEEK_SET);
	printf("Total audio size: %li \n", size);

	//Send audio Size
	printf("Sending audio Size\n");
	send(socket, (void *)&size, sizeof(size), 0);

	printf("Sending audio as Byte Array\n");

	do
	{
		//Read while we get errors that are due to signals.
		stat = recv(socket, read_buffer, 255, 0);
		printf("Bytes read: %li \n", stat);

	} while (stat < 0);

	printf("Received data in socket\n");
	printf("Socket data: %s\n", read_buffer);

	while (!feof(audio))
	{

		//Read from the file into our send buffer
		read_size = fread(send_buffer, 1, sizeof(send_buffer), audio);

		//Send data through our socket 
		do
		{
			stat = send(socket, send_buffer, read_size, 0);
		} while (stat < 0);

		printf("Packet %li, sent %li bytes.\n", packet_index, read_size);

		packet_index++;
	}

	return 0;
}


这是一个更复杂的版本,可以在linux(在UBUNTU上测试)和Windows(测试OS Win7)上编译。 br />
它传输更多文件。它没有优化。它不需要所有检查。



包含文件preamble.h

This is a more sophisticated version that can be compiled on linux (tested on UBUNTU) and on windows (test OS Win7).
It transfers more files. It is not optimized. It has not all checks required.

Include file preamble.h
//File preamble.h

typedef struct
{
	long long llSize;
	char FileName[500];
	char Reserved[8];
} FILEDATA;





服务器:



The server:

	#ifdef __linux__
	#define _FILE_OFFSET_BITS 64
	#else
	#include <winsock2.h>
	#endif

	#include <stdio.h>
	#include <stdlib.h>
	#include <errno.h>
	#ifdef __linux__
	#include <unistd.h>
	#include <string.h>
	#include <sys/socket.h>
	#include <sys/ioctl.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
	#define WINBIN
	#else
	#define WINBIN "b"
	#define close closesocket
	#define ftell _ftell64
	#define ioctl ioctlsocket
	typedef int socklen_t;
	#endif
	#include "preamble.h"

char *file[] = { "mp3.mp3"  ,
				 "image.jpg",
				 "film.mkv"
				};
 #ifdef __linux__
 char Path[] = "/media/sf_UnixShares/";
 #else
 char Path[] = "C:\\Users\\UnixShares\\";
 #endif

int SendFile(int socket, char *FileName)
{
	FILEDATA fd;
	FILE *fp;
	long int read_size, stat, packet_index;
	long long int size=0;
	char send_buffer[512];
	char read_buffer[512];
	char LocFname[1024];
	packet_index = 1;

	memset(&fd, 0, sizeof(fd));
	strcpy(LocFname, Path);
	strcat(LocFname, FileName);
	fp = fopen(LocFname, "r" WINBIN);
	
	if (fp == NULL)
	{
		printf("Error Opening File \"%s\"\n", FileName);
		exit(-1);
	}

	printf("Getting file Size\n");

	fseek(fp, 0, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	fd.llSize = size;
	printf("Total file size: %lli \n", size);

	//Send file preamble
	strcpy(fd.FileName, FileName);
	printf("Sending file preamble\n");
	send(socket, (void *)&fd, sizeof(fd), 0);

	//Wait for client acknowledge
	do
	{
		//Read while we get errors that are due to signals.
		stat = recv(socket, read_buffer, 255, 0);
		printf("Bytes read: %li \n", stat);
	} while (stat < 0);
	printf("Received preamble acknowledge <%5s>\n", read_buffer);
	if (strncmp("OK", read_buffer, 5))
	{
		printf ("Transfer aborted!\n");
		return 0;
	}

	printf("Press Enter to send file: ...");
	getchar();
	printf("\rSending file\n");

	while (!feof(fp))
	{
		//Read from the file into our send buffer
		read_size = fread(send_buffer, 1, sizeof(send_buffer), fp);

		//Send data through our socket 
		do
		{
			stat = send(socket, send_buffer, read_size, 0);
		} while (stat < 0);

		printf("\rPacket %li, sent %li bytes.", packet_index, read_size);

		packet_index++;

		//Zero out our send buffer
		memset(send_buffer, 0, sizeof(send_buffer));
	}
	
	printf("\nFile sent!\n");

	return 1;
}

int main(int argc, char *argv[])
{
	long long int socket_desc, new_socket, c;
	struct sockaddr_in server, client;

 #if defined(__WIN32__) || defined(_WIN32)
    //----------------------
    // Declare and initialize variables.
    int iResult;
    WSADATA wsaData;

    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR)
	{
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }
 #endif

	//Create socket
	socket_desc = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_desc == -1)
	{
		printf("Could not create socket");
	}

	//Prepare the sockaddr_in structure
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(6888);

	//Bind

	if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
	{
		puts("bind failed");
		return 1;
	}

	puts("Bind completed");

	//Listen
	listen(socket_desc, 3);

	//Accept and incoming connection
	puts("Waiting for incoming connections...");
	c = sizeof(struct sockaddr_in);

	new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *) & c);

	fflush(stdout);

	if (new_socket < 0)
	{
		perror("Accept Failed");
		return 1;
	}
	else
		puts("Connection accepted");

	for (int i=0; i<3; i++)
		if (!SendFile(new_socket, file[i]))
		{
			printf ("Client required tx abort!\n");
			break;
		}
		
	//Tell client that transfer is finished sending a file len=0
	FILEDATA fd = {0};
	send(new_socket, (void *)&fd, sizeof(fd), 0);

	close(new_socket);
	close(socket_desc);
	fflush(stdout);
	return 0;
}





客户:



The Client:

	#ifdef __linux__
	#define _FILE_OFFSET_BITS 64
	#else
	#include <winsock2.h>
	#endif

	#include <stdio.h>
	#include <stdlib.h>
	#include <errno.h>
	#ifdef __linux__
	#include <unistd.h>
	#include <string.h>
	#include <sys/socket.h>
	#include <sys/ioctl.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
	#define WINBIN
	#else
	#define WINBIN "b"
	#define close closesocket
	#define ftell _ftell64
	#define ioctl ioctlsocket
	typedef int socklen_t;
	#endif
	#include "preamble.h"

/*
 * This function is to be used once we have confirmed that an fp
 * is to be sent.
 * It should read and output a file.
 */
int ReceiveFile(int socket)
{

	long int buffersize = 0;
	long int read_size;
	long long int recv_size = 0;

	FILE *fp;
	FILEDATA fd;

	//Find the size of the fp
	recv(socket, (void *)&fd, sizeof(fd), 0);

	//Make sure that the size is bigger than 0
	if (fd.llSize <= 0)
	{
		printf("End of transfer or error (len=0)\n");
		return 0;
	}

	fp = fopen(fd.FileName, "w" WINBIN);

	if (fp == NULL)
	{
		printf("Error! Cannot create file \"%s\".\n", fd.FileName);
		//Send failure to server
		send(socket, "ABORT", 6, 0);
		return 0;
	}

	printf ("Receiving %lld bytes for file \"%s\".\n", fd.llSize, fd.FileName);
	
	//Send our verification signal
	send(socket, "OK", 3, 0);

	//Loop while we have not received the entire file yet

	while (recv_size < fd.llSize)
	{
		ioctl(socket, FIONREAD, (unsigned long int *)&buffersize);

		//We check to see if there is data to be read from the socket 
		if (buffersize <= 0)
			continue;

		//The protocol put all data together :(
		//If more data of required is available
		//just peek what we need.
		if (buffersize > (fd.llSize - recv_size))
			buffersize = fd.llSize - recv_size;

		char *pBuf = malloc(buffersize);
		if (!pBuf)
		{
			fprintf(stderr, "\nMemory Error. Cannot allocate!\n");
			exit(-1);
		}

		read_size = recv(socket, pBuf, buffersize, 0);
		if (read_size  < 0)
		{
			printf("\n%s", strerror(errno));
			return 0;
		}

		//Write the currently read data into our fp file
		fwrite(pBuf, 1, buffersize, fp);

		free(pBuf);

		//Increment the total number of bytes read
		recv_size += read_size;
		
		printf("\rReceived %lli bytes out of %lli.", recv_size, fd.llSize);
	}

	fclose(fp);
	printf("\nFile successfully Received! \n");
	return 1;
}

int main(int argc, char *argv[])
{
	long long int socket_desc;
	struct sockaddr_in server;

	//printmonth(11, 2015, 30);
	//exit(0);

 #if defined(__WIN32__) || defined(_WIN32)
    //----------------------
    // Declare and initialize variables.
    int iResult;
    WSADATA wsaData;

    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR)
	{
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }
 #endif

	//Create socket
	socket_desc = socket(AF_INET, SOCK_STREAM, 0);

	if (socket_desc == -1)
	{
		printf("Could not create socket \n");
	}

	memset(&server, 0, sizeof(server));
	//server.sin_addr.s_addr = inet_addr("10.170.0.40");
	server.sin_addr.s_addr = inet_addr("127.0.0.1");
	server.sin_family = AF_INET;
	server.sin_port = htons(6888);

	//Connect to remote server
	if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
	{
		// printf(strerror(errno));
		close(socket_desc);
		printf("Connect Error \n");
		return -1;
	}

	puts("Connected \n");

	while (ReceiveFile(socket_desc))
		;

	close(socket_desc);

	return 0;
}


这篇关于是否可以在两个系统中使用tcp / ip协议运行客户端服务器通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆