1. 程式人生 > >利用TCP完成檔案傳輸的設計和實現

利用TCP完成檔案傳輸的設計和實現

實驗課的內容,建立tcp 實現檔案的傳輸,需要注意的一個地方就是,客戶端和伺服器端不要放在一起,檔案可以放在客戶端,絕對路徑就可以。還有就是自己寫一個makefile 

服務端:

建立socket

使用bind繫結套接字

使用listen監聽

使用accept接受連線請求 accept返回新的套接字描述符

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8789						/*偵聽埠地址*/
#define BACKLOG 2						/*偵聽佇列長度*/

int main(int argc, char *argv[])
{
	int ss,sc;		/*ss為伺服器的socket描述符,sc為客戶端的socket描述符*/
	struct sockaddr_in server_addr;	/*伺服器地址結構*/
	struct sockaddr_in client_addr;	/*客戶端地址結構*/
	int err;							/*返回值*/
	pid_t pid;							/*分叉的進行ID*/

	/*建立一個流式套接字*/
	ss = socket(AF_INET, SOCK_STREAM, 0);
	if(ss < 0){							/*出錯*/
		printf("socket error\n");
		return -1;
	}

	/*設定伺服器地址*/
	bzero(&server_addr, sizeof(server_addr));			/*清零*/
	server_addr.sin_family = AF_INET;					/*協議族*/
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);	/*本地地址*/
	server_addr.sin_port = htons(PORT);				/*伺服器埠*/

	/*繫結地址結構到套接字描述符*/
	err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if(err < 0){/*出錯*/
		printf("bind error\n");
		return -1;
	}

	/*設定偵聽*/
	err = listen(ss, BACKLOG);
	if(err < 0){										/*出錯*/
		printf("listen error\n");
		return -1;
	}

		/*主迴圈過程*/
	for(;;)	{
		socklen_t addrlen = sizeof(struct sockaddr);

		sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen);
		/*接收客戶端連線*/
		if(sc < 0){							/*出錯*/
			continue;						/*結束本次迴圈*/
		}

		/*建立一個新的程序處理到來的連線*/
		pid = fork();						/*分叉程序*/
		if( pid == 0 ){						/*子程序中*/
			process_conn_server(sc);		/*處理連線*/
			close(ss);						/*在子程序中關閉伺服器的偵聽*/
			return 0;
		}else{
			close(sc);						/*在父程序中關閉客戶端的連線*/
		}
	}
}
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 1024

/*伺服器對客戶端的處理*/
void process_conn_server(int s)
{
	ssize_t size = 0;
	char buffer[BUFFER_SIZE];
	FILE *stream;
	
	strcpy(buffer,"請輸入傳輸的檔案路徑:\n");
	write(s, buffer, BUFFER_SIZE);
	int length=0;
	char buffer_add[BUFFER_SIZE]={'\0'};
	for(;;){
		size = read(s, buffer, BUFFER_SIZE-length);
		if(size <= 0){
			return;
		}
		strcat(buffer_add, buffer);
		length+=size;
		if(length>=BUFFER_SIZE) break;
	}

	if((stream=fopen(buffer_add, "w"))==NULL) return;
	for(;;){
		size = read(s, buffer, BUFFER_SIZE);
		if(size <= 0){
			return;
		}
		int write_len=fwrite(buffer, sizeof(char), size, stream);
	}
	fclose(stream);
}

客戶端:

建立socket

確定伺服器scokaddr_in結構體 點分十進位制IP轉換

使用connect連線 開啟檔案

準備緩衝區 緩衝區初始化置空

將檔案內容讀入緩衝區

使用send將緩衝區內容傳送到伺服器

檔案內容傳送完成

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8888								/*偵聽埠地址*/

int main(int argc, char *argv[])
{
	int s;										/*s為socket描述符*/
	struct sockaddr_in server_addr;			/*伺服器地址結構*/
	
	s = socket(AF_INET, SOCK_STREAM, 0); 		/*建立一個流式套接字 */
	if(s < 0){									/*出錯*/
		printf("socket error\n");
		return -1;
	}	
	
	/*設定伺服器地址*/
	bzero(&server_addr, sizeof(server_addr));	/*清零*/
	server_addr.sin_family = AF_INET;					/*協議族*/
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);	/*本地地址*/
	server_addr.sin_port = htons(PORT);				/*伺服器埠*/
	
	/*將使用者輸入的字串型別的IP地址轉為整型*/
	inet_pton(AF_INET, argv[1], &server_addr.sin_addr);	
	/*連線伺服器*/
	connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
	process_conn_client(s);						/*客戶端處理過程*/
	close(s);									/*關閉連線*/
	return 0;
}
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 1024

/*客戶端的處理過程*/
void process_conn_client(int s)
{
	ssize_t size = 0;
	char buffer[BUFFER_SIZE];
	FILE *stream;

	int length=0;
	char buffer_add[BUFFER_SIZE]={'\0'};
	for(;;){
		size = read(s, buffer, BUFFER_SIZE-length);
		if(size <= 0){
			return;
		}
		strcat(buffer_add, buffer);
		length+=size;
		if(length>=BUFFER_SIZE) break;
	}
	printf("%s", buffer_add);

	scanf("%s", buffer);
	write(s, buffer, BUFFER_SIZE);

	if((stream=fopen(buffer, "r"))==NULL) return;
	printf("ing...\n");
	for(;;){
		size = fread(buffer, sizeof(char), BUFFER_SIZE, stream);
		if(size <= 0){
			return;
		}
		write(s, buffer, size);
	}
	fclose(stream);
}