[代碼] c代碼 server部分
001 |
server.c |
002 |
|
003 |
====================================================================
|
004 |
|
005 |
#include <netinet/in.h> // for sockaddr_in
|
006 |
#include <sys/types.h> // for socket
|
007 |
#include <sys/socket.h> // for socket
|
008 |
#include <stdio.h> // for printf
|
009 |
#include <stdlib.h> // for exit
|
010 |
#include <string.h> // for bzero
|
011 |
/* |
012 |
#include <sys/types.h> |
013 |
#include <sys/stat.h> |
014 |
#include <fcntl.h> |
015 |
#include <unistd.h> |
016 |
*/ |
017 |
#define HELLO_WORLD_SERVER_PORT 6666
|
018 |
#define LENGTH_OF_LISTEN_QUEUE 20
|
019 |
#define BUFFER_SIZE 1024
|
020 |
#define FILE_NAME_MAX_SIZE 512
|
021 |
|
022 |
int
main( int argc,
char **argv)
|
023 |
{ |
024 |
//設置一個socket地址結構server_addr,代表服務器internet地址, 端口
|
025 |
struct
sockaddr_in server_addr; |
026 |
bzero(&server_addr, sizeof (server_addr));
//把一段內存區的內容全部設置爲0 |
027 |
server_addr.sin_family = AF_INET;
|
028 |
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
|
029 |
server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
|
030 |
|
031 |
//創建用於internet的流協議(TCP)socket,用server_socket代表服務器socket
|
032 |
int
server_socket = socket(PF_INET,SOCK_STREAM,0); |
033 |
if ( server_socket < 0)
|
034 |
{
|
035 |
printf ( "Create Socket Failed!" );
|
036 |
exit (1);
|
037 |
}
|
038 |
{ |
039 |
int
opt =1; |
040 |
setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&opt, sizeof (opt));
|
041 |
} |
042 |
|
043 |
//把socket和socket地址結構聯繫起來
|
044 |
if ( bind(server_socket,( struct
sockaddr*)&server_addr, sizeof (server_addr)))
|
045 |
{
|
046 |
printf ( "Server Bind Port : %d Failed!" , HELLO_WORLD_SERVER_PORT);
|
047 |
exit (1);
|
048 |
}
|
049 |
|
050 |
//server_socket用於監聽
|
051 |
if
( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )
|
052 |
{
|
053 |
printf ( "Server Listen Failed!" );
|
054 |
exit (1);
|
055 |
}
|
056 |
while
(1) //服務器端要一直運行
|
057 |
{
|
058 |
//定義客戶端的socket地址結構client_addr
|
059 |
struct
sockaddr_in client_addr; |
060 |
socklen_t length =
sizeof (client_addr);
|
061 |
|
062 |
//接受一個到server_socket代表的socket的一個連接
|
063 |
//如果沒有連接請求,就等待到有連接請求--這是accept函數的特性
|
064 |
//accept函數返回一個新的socket,這個socket(new_server_socket)用於同連接到的客戶的通信
|
065 |
//new_server_socket代表了服務器和客戶端之間的一個通信通道
|
066 |
//accept函數把連接到的客戶端信息填寫到客戶端的socket地址結構client_addr中
|
067 |
int
new_server_socket = accept(server_socket,( struct
sockaddr*)&client_addr,&length); |
068 |
if
( new_server_socket < 0) |
069 |
{
|
070 |
printf ( "Server Accept Failed!\n" );
|
071 |
break ;
|
072 |
}
|
073 |
|
074 |
char
buffer[BUFFER_SIZE]; |
075 |
bzero(buffer, BUFFER_SIZE);
|
076 |
length = recv(new_server_socket,buffer,BUFFER_SIZE,0);
|
077 |
if
(length < 0) |
078 |
{
|
079 |
printf ( "Server Recieve Data Failed!\n" );
|
080 |
break ;
|
081 |
}
|
082 |
char
file_name[FILE_NAME_MAX_SIZE+1]; |
083 |
bzero(file_name, FILE_NAME_MAX_SIZE+1);
|
084 |
strncpy (file_name, buffer,
strlen (buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE: strlen (buffer));
|
085 |
// int fp = open(file_name, O_RDONLY);
|
086 |
// if( fp < 0 ) |
087 |
printf ( "%s\n" ,file_name);
|
088 |
FILE
* fp = fopen (file_name, "r" );
|
089 |
if (NULL == fp )
|
090 |
{
|
091 |
printf ( "File:\t%s Not Found\n" , file_name);
|
092 |
}
|
093 |
else |
094 |
{
|
095 |
bzero(buffer, BUFFER_SIZE);
|
096 |
int
file_block_length = 0; |
097 |
// while( (file_block_length = read(fp,buffer,BUFFER_SIZE))>0)
|
098 |
while ( (file_block_length =
fread (buffer, sizeof ( char ),BUFFER_SIZE,fp))>0)
|
099 |
{
|
100 |
printf ( "file_block_length = %d\n" ,file_block_length);
|
101 |
//發送buffer中的字符串到new_server_socket,實際是給客戶端
|
102 |
if (send(new_server_socket,buffer,file_block_length,0)<0)
|
103 |
{
|
104 |
printf ( "Send File:\t%s Failed\n" , file_name);
|
105 |
break ;
|
106 |
}
|
107 |
bzero(buffer, BUFFER_SIZE);
|
108 |
}
|
109 |
// close(fp); |
110 |
fclose (fp);
|
111 |
printf ( "File:\t%s Transfer Finished\n" ,file_name);
|
112 |
}
|
113 |
//關閉與客戶端的連接
|
114 |
close(new_server_socket);
|
115 |
}
|
116 |
//關閉監聽用的socket
|
117 |
close(server_socket);
|
118 |
return
0; |
119 |
} |
[代碼] c代碼 client部分
001 |
client.c |
002 |
|
003 |
#include <netinet/in.h> // for sockaddr_in
|
004 |
#include <sys/types.h> // for socket
|
005 |
#include <sys/socket.h> // for socket
|
006 |
#include <stdio.h> // for printf
|
007 |
#include <stdlib.h> // for exit
|
008 |
#include <string.h> // for bzero
|
009 |
/* |
010 |
#include <sys/types.h> |
011 |
#include <sys/stat.h> |
012 |
#include <fcntl.h> |
013 |
#include <unistd.h> |
014 |
*/ |
015 |
|
016 |
#define HELLO_WORLD_SERVER_PORT 6666
|
017 |
#define BUFFER_SIZE 1024
|
018 |
#define FILE_NAME_MAX_SIZE 512
|
019 |
|
020 |
int
main( int argc,
char **argv)
|
021 |
{ |
022 |
if
(argc != 2) |
023 |
{
|
024 |
printf ( "Usage: ./%s ServerIPAddress\n" ,argv[0]);
|
025 |
exit (1);
|
026 |
}
|
027 |
|
028 |
//設置一個socket地址結構client_addr,代表客戶機internet地址, 端口
|
029 |
struct
sockaddr_in client_addr; |
030 |
bzero(&client_addr, sizeof (client_addr));
//把一段內存區的內容全部設置爲0 |
031 |
client_addr.sin_family = AF_INET;
//internet協議族 |
032 |
client_addr.sin_addr.s_addr = htons(INADDR_ANY); //INADDR_ANY表示自動獲取本機地址
|
033 |
client_addr.sin_port = htons(0);
//0表示讓系統自動分配一個空閒端口 |
034 |
//創建用於internet的流協議(TCP)socket,用client_socket代表客戶機socket
|
035 |
int
client_socket = socket(AF_INET,SOCK_STREAM,0); |
036 |
if ( client_socket < 0)
|
037 |
{
|
038 |
printf ( "Create Socket Failed!\n" );
|
039 |
exit (1);
|
040 |
}
|
041 |
//把客戶機的socket和客戶機的socket地址結構聯繫起來
|
042 |
if ( bind(client_socket,( struct
sockaddr*)&client_addr, sizeof (client_addr)))
|
043 |
{
|
044 |
printf ( "Client Bind Port Failed!\n" );
|
045 |
exit (1);
|
046 |
}
|
047 |
|
048 |
//設置一個socket地址結構server_addr,代表服務器的internet地址, 端口
|
049 |
struct
sockaddr_in server_addr; |
050 |
bzero(&server_addr, sizeof (server_addr));
|
051 |
server_addr.sin_family = AF_INET;
|
052 |
if (inet_aton(argv[1],&server_addr.sin_addr) == 0)
//服務器的IP地址來自程序的參數 |
053 |
{
|
054 |
printf ( "Server IP Address Error!\n" );
|
055 |
exit (1);
|
056 |
}
|
057 |
server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
|
058 |
socklen_t server_addr_length =
sizeof (server_addr);
|
059 |
//向服務器發起連接,連接成功後client_socket代表了客戶機和服務器的一個socket連接
|
060 |
if (connect(client_socket,( struct
sockaddr*)&server_addr, server_addr_length) < 0) |
061 |
{
|
062 |
printf ( "Can Not Connect To %s!\n" ,argv[1]);
|
063 |
exit (1);
|
064 |
}
|
065 |
|
066 |
char
file_name[FILE_NAME_MAX_SIZE+1]; |
067 |
bzero(file_name, FILE_NAME_MAX_SIZE+1);
|
068 |
printf ( "Please Input File Name On Server:\t" );
|
069 |
scanf ( "%s" , file_name);
|
070 |
|
071 |
char
buffer[BUFFER_SIZE]; |
072 |
bzero(buffer,BUFFER_SIZE);
|
073 |
strncpy (buffer, file_name,
strlen (file_name)>BUFFER_SIZE?BUFFER_SIZE: strlen (file_name));
|
074 |
//向服務器發送buffer中的數據
|
075 |
send(client_socket,buffer,BUFFER_SIZE,0);
|
076 |
|
077 |
// int fp = open(file_name, O_WRONLY|O_CREAT);
|
078 |
// if( fp < 0 ) |
079 |
FILE
* fp = fopen (file_name, "w" );
|
080 |
if (NULL == fp )
|
081 |
{
|
082 |
printf ( "File:\t%s Can Not Open To Write\n" , file_name);
|
083 |
exit (1);
|
084 |
}
|
085 |
|
086 |
//從服務器接收數據到buffer中
|
087 |
bzero(buffer,BUFFER_SIZE);
|
088 |
int
length = 0; |
089 |
while ( length = recv(client_socket,buffer,BUFFER_SIZE,0))
|
090 |
{
|
091 |
if (length < 0)
|
092 |
{
|
093 |
printf ( "Recieve Data From Server %s Failed!\n" , argv[1]);
|
094 |
break ;
|
095 |
}
|
096 |
// int write_length = write(fp, buffer,length);
|
097 |
int
write_length = fwrite (buffer, sizeof ( char ),length,fp);
|
098 |
if
(write_length<length) |
099 |
{
|
100 |
printf ( "File:\t%s Write Failed\n" , file_name);
|
101 |
break ;
|
102 |
}
|
103 |
bzero(buffer,BUFFER_SIZE);
|
104 |
}
|
105 |
printf ( "Recieve File:\t %s From Server[%s] Finished\n" ,file_name, argv[1]);
|
106 |
|
107 |
close(fp);
|
108 |
//關閉socket
|
109 |
close(client_socket);
|
110 |
return
0; |
111 |
} |
[代碼] open等,fopen等說明
01 |
某些註釋部分,open,read,write被 fopen , fread , fwrite 替換。
|
02 |
|
03 |
說明一下: |
04 |
fopen ,
fclose ,
fread , fwrite ,
fgetc ,
fgets , fputc ,
fputs ,
freopen , fseek ,
ftell ,
rewind 等 |
05 |
緩衝文件系統 |
06 |
緩衝文件系統的特點是:在內存開闢一個“緩衝區”,爲程序中的每一個文件使用,當執行讀文件的操作時,
|
07 |
從磁盤文件將數據先讀入內存“緩衝區”, 裝滿後再從內存“緩衝區”依此讀入接收的變量。執行寫文件的
|
08 |
操作時,先將數據寫入內存“緩衝區”,待內存“緩衝區”裝滿後再寫入文件。由此可以看出,內存
|
09 |
“緩衝區”的大小,影響着實際操作外存的次數,內存“緩衝區”越大,則操作外存的次數就少,
|
10 |
執行速度就快、效率高。一般來說,文件“緩衝區”的大小隨機器 而定。
|
11 |
|
12 |
open, close, read, write, getc ,
getchar ,
putc , putchar
等 |
13 |
非緩衝文件系統 |
14 |
非緩衝文件系統是藉助文件結構體指針來對文件進行管理,通過文件指針來對文件進行訪問,既可以讀寫字符、
|
15 |
字符串、格式化數據,也可以讀寫二進制數 據。非緩衝文件系統依賴於操作系統,通過操作系統的功能對
|
16 |
文件進行讀寫,是系統級的輸入輸出,它不設文件結構體指針,只能讀寫二進制文件,但效率高、速度快,
|
17 |
由於ANSI標準不再包括非緩衝文件系統,因此建議大家最好不要選擇它。
|
18 |
|
19 |
open等屬於低級IO, |
20 |
fopen 等是高級IO。
|
21 |
|
22 |
open等返回一個文件描述符(用戶程序區的), |
23 |
fopen 等返回一個文件指針。
|
24 |
|
25 |
open等無緩衝, fopen 等有緩衝。
|
26 |
|
27 |
fopen 等是在open等的基礎上擴充而來的,在大多數情況下,用 fopen 等。
|
28 |
|
29 |
open 是系統調用 返回的是文件句柄,文件的句柄是文件在文件描述符表裏的索引,
|
30 |
fopen 是C的庫函數,返回的是一個指向文件結構的指針。 |