開始行:
#norelated
*Linux socket プログラミング/POP3 クライアントプログラム
*目次 [#cdb70484]
#contents
*概要 [#j1c53e91]
こんどは POP3 のクライアントプログラムです。MTA(メール転...
見た目かなり汚くなってしまいましたが、要所要所を変えれば...
*プログラムのイメージ [#j7e59410]
このプログラムで使われる関数のイメージを以下に示します。...
|POP3 サーバ |BGCOLOR(white):|このプログラム|h
|recv()|BGCOLOR(white):USER ID 送信&br;<-----------------...
|recv()|BGCOLOR(white):PASSWORD 送信&br;<----------------...
|recv()|BGCOLOR(white):LIST コマンド送信&br;<------------...
|send()|BGCOLOR(white):LIST受信&br;----------------------...
|recv()|BGCOLOR(white):RETR コマンド送信&br;<------------...
|send()|BGCOLOR(white):メッセージ受信&br;----------------...
*ソースコード [#ne1ca8c4]
CENTER:[[mailp.c>http://github.com/kaizawa/linux-socket/r...
1 /*
2 * POP3 client program
3 * mailp.c
4 * cc mailp.c -lnsl -o mailp
5 */
6
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15
16 #define BUFMAX 256
17 #define PORT_NO 110
18
19 void read_msg();
20 void print_err(char *);
21
22 extern int h_errno;
23 int net;
24 int nbyte;
25 char r_msg[BUFMAX];
26 char s_msg[BUFMAX];
27 char input[6];
28
29 int
30 main(int argc, char *argv[])
31 {
32 struct hostent *host;
33 struct servent *serv;
34 struct sockaddr_in sa;
35 char p_list[] = "LIST\n";
36 char p_user[] = "USER pop_user\n";
37 char p_pass[] = "PASS pop_password\n";
38 char p_quit[] = "QUIT\n";
39
40 if (argc != 2) {
41 printf("Usage: %s hostname\n", argv[0]);
42 exit(1);
43 }
44
45 /*
46 * Check Host name
47 */
48 if ((host = gethostbyname(argv[1])) == NULL){
49 herror("gethostbyname()");
50 close(net);
51 exit(1);
52 }
53
54 memset(&sa,0, sizeof(struct sockaddr_in));
55 memcpy(&sa.sin_addr, host->h_addr, sizeof(str...
56
57 sa.sin_family = AF_INET;
58 sa.sin_port = htons(PORT_NO);
59
60 /*
61 * Make socket
62 */
63 if((net = socket(AF_INET, SOCK_STREAM, 0)) < 0)
64 print_err("socket()");
65
66 /*
67 * Connect to the mail server
68 */
69 if (connect(net, (struct sockaddr *)&sa, size...
70 print_err("connect()");
71
72 /*
73 * Receive connection messages from server
74 */
75 memset(r_msg,0,BUFMAX);
76 if( recv(net,r_msg,BUFMAX,0) < 0)
77 print_err("recv()");
78 printf("%s",r_msg);
79
80 /*
81 * Send user name
82 */
83 nbyte = strlen( p_user );
84 if( send(net,p_user,nbyte,0) < 0)
85 print_err("send()");
86
87 memset(r_msg,0,BUFMAX);
88 if( recv(net,r_msg,BUFMAX,0) < 0)
89 print_err("recv");
90 printf("%s",r_msg);
91
92 /*
93 * Send password
94 */
95 nbyte = strlen(p_pass);
96 if( send(net,p_pass,nbyte,0) < 0 )
97 print_err("send()");
98
99 memset(r_msg,0,BUFMAX);
100 if( recv(net,r_msg,BUFMAX,0) < 0)
101 print_err("recv()");
102 printf("%s",r_msg);
103
104 /*
105 * Request mail list & Select letter number
106 */
107 while(1){ /* loop start */
108 nbyte = strlen( p_list );
109 if( send(net,p_list,nbyte,0) < 0 )
110 print_err("send()");
111 while(1){
112 memset(r_msg,0,BUFMAX);
113 if( recv(net,r_msg,BUFMAX,0) < 0)
114 print_err("recv()");
115 printf("%s",r_msg);
116 if ( strstr( r_msg, "\n.") != NULL) {
117 printf("\n");
118 break;
119 }
120 }
121
122 /*
123 * Enter letter number
124 */
125 printf("Enter the number you want to read...
126 if ( scanf("%5s", input) < 0)
127 print_err("scanf()");
128
129 if ( input[0] == 'q' ) {
130 nbyte = strlen( p_quit );
131 if( send(net,p_quit,nbyte,0) < 0)
132 print_err("send()");
133 memset(r_msg,0,BUFMAX);
134 if( recv(net,r_msg,BUFMAX,0) < 0)
135 print_err("recv()");
136 printf("%s\n",r_msg);
137 /* Normal closure process */
138 if (shutdown(net, 2) < 0)
139 print_err("shutdown()");
140 close(net);
141 exit(0);
142 }
143 if( (isdigit(input[0])) == 0){
144 printf("Input error\n");
145 continue;
146 }
147 read_msg();
148 } /* loop end */
149 }
150
151 /************************************************...
152 * read_msg()
153 *
154 * Retrieve and print email message from the mai...
155 ************************************************...
156 void
157 read_msg()
158 {
159 sprintf(s_msg,"RETR %s\n",input);
160 nbyte = strlen(s_msg);
161 if( send(net,s_msg,nbyte,0) < 0 )
162 print_err("send()");
163 while(1){
164 memset(r_msg,0,BUFMAX);
165 if( recv(net,r_msg,BUFMAX,0) < 0)
166 print_err("recv()");
167 printf("%s",r_msg);
168 if( strstr(r_msg,"\n.") != NULL ){
169 printf("\n");
170 break;
171 }
172 }
173 return;
174 }
175
176 void
177 print_err(char *func)
178 {
179 perror(func);
180 close(net);
181 exit(1);
182 }
ソースファイル [[mailp.c>http://github.com/kaizawa/linux-...
*実行例 [#p046daeb]
このプログラムの実行例を示します。
プログラム名の後に引数として POP3 サーバ名、または IP ア...
% ./mailp mail.example.com
+OK POP3 mail v2001.80 server ready
+OK User name accepted, password please
+OK Mailbox open, 2 messages
+OK Mailbox scan listing follows
1 392
2 395
.
Enter the number you want to read.( q for quit)
1
+OK 392 octets
Return-Path: <root><root@mail.example.com>
Received: (from root@localhost)
by mail.example.com (8.8.7/8.8.7) id AAA21525
for pop_user; Thu, 1 Jul 1999 00:24:05 +0900
Date: Thu, 1 Jul 1999 00:24:05 +0900
From: root
Message-Id: <199906301524.AAA21525@mail.example.com>
To: pop_user@mail.example.com
Subject: test1
X-UIDL: 0beb13dbeab34ae6e3549b3f5ea2872c
Status: RO
This is a test mail from root.
Can you read?
.
+OK 2 messages (787 octets)
1 392
2 395
.
Enter the number you want to read( q for quit)
q
+OK Sayonara
*解説 [#zdd7edf1]
以下にこのプログラムの説明をします。最初にサーバの名前を ...
40 if (argc != 2) {
41 printf("Usage: %s hostname\n", argv[0]);
42 exit(1);
43 }
ここではプログラムの起動時に引数を指定しています。プログ...
48 if ((host = gethostbyname(argv[1])) == NULL){
49 herror("gethostbyname()");
50 close(net);
51 exit(1);
52 }
48 行目ではコマンドの引数であるサーバ名から gethostbyname...
hosts: files dns
たとえは nsswitch.conf が上記のようになっていれば最初に /...
|>|gethostbyname()|h
|概要|ホスト情報入手|
|インクルードファイル | #include <netdb.h>|
|形式| struct hostent *gethostbyname(const char *name);|
|引数| const char *name: サーバ名が格納されている文字配...
|戻り値 |成功時: hostent 構造体にホスト情報をセットし、...
54 memset(&sa,0, sizeof(struct sockaddr_in));
54行目は sockaddr_in 構造体である「sa」に 0 つまり NULL ...
63〜70 行目までは「ポート番号調査」のところで説明したのと...
80 /*
81 * Send user name
82 */
83 nbyte = strlen( p_user );
84 if( send(net,p_user,nbyte,0) < 0)
85 print_err("send()");
86
87 memset(r_msg,0,BUFMAX);
88 if( recv(net,r_msg,BUFMAX,0) < 0)
89 print_err("recv");
90 printf("%s",r_msg);
ここでは send()システムコールを使って p_user(= USER p...
成功するとパスワードを要求するメッセージがサーバから届く...
|>|send()|h
|概要|メッセージの送信|
|インクルードファイル | #include <sys/types.h>&br;#includ...
|形式| int send(int s, const void *msg, int len, unsigne...
|引数 |int s : socket 記述子&br;const void *msg: 送信...
|戻り値 |成功時: 送信されバイト数&br;エラー: -1|
~
|>|recv()|h
|概要|メッセージの受信|
|インクルードファイル | #include <sys/types.h>&br;#includ...
|形式| int recv(int s, void *msg, int len, unsigned int ...
|引数 |int s : socket 記述子&br;const void *msg: 受信...
|戻り値 |成功時: 受信したバイト数&br;エラー: -1|
95〜102 行目も同様です。プログラムの最初で宣言している p_...
107〜148 行目 は while() を使ってループしています。ここで...
104 /*
105 * Request mail list & Select letter number
106 */
107 while(1){ /* loop start */
108 nbyte = strlen( p_list );
109 if( send(net,p_list,nbyte,0) < 0 )
110 print_err("send()");
111 while(1){
112 memset(r_msg,0,BUFMAX);
113 if( recv(net,r_msg,BUFMAX,0) < 0)
114 print_err("recv()");
115 printf("%s",r_msg);
116 if ( strstr( r_msg, "\n.") != NULL) {
117 printf("\n");
118 break;
119 }
120 }
ここでは p_list という文字列を送信しているのはこれまでと...
while() の終了(break)する条件については少々無理があるの...
122 /*
123 * Enter letter number
124 */
125 printf("Enter the number you want to read...
126 if ( scanf("%5s", input) < 0)
127 print_err("scanf()");
128
129 if ( input[0] == 'q' ) {
130 nbyte = strlen( p_quit );
131 if( send(net,p_quit,nbyte,0) < 0)
132 print_err("send()");
133 memset(r_msg,0,BUFMAX);
134 if( recv(net,r_msg,BUFMAX,0) < 0)
135 print_err("recv()");
136 printf("%s\n",r_msg);
137 /* Normal closure process */
138 if (shutdown(net, 2) < 0)
139 print_err("shutdown()");
140 close(net);
141 exit(0);
142 }
143 if( (isdigit(input[0])) == 0){
144 printf("Input error\n");
145 continue;
146 }
126行目では scanf()でユーザからのメール番号の入力を待ちま...
129〜142 行目では、もし「q」という文字が入力された場合サ...
143 if( (isdigit(input[0])) == 0){
144 printf("Input error\n");
145 continue;
146 }
147 read_msg();
「q」以外の文字が入力された場合にはまず、isdigit(3) 関数...
156 void
157 read_msg()
158 {
159 sprintf(s_msg,"RETR %s\n",input);
160 nbyte = strlen(s_msg);
161 if( send(net,s_msg,nbyte,0) < 0 )
162 print_err("send()");
163 while(1){
164 memset(r_msg,0,BUFMAX);
165 if( recv(net,r_msg,BUFMAX,0) < 0)
166 print_err("recv()");
167 printf("%s",r_msg);
168 if( strstr(r_msg,"\n.") != NULL ){
169 printf("\n");
170 break;
171 }
172 }
173 return;
174 }
159 行目では 126 行目でユーザから受け取ったメッセージ番号...
メッセージの表示が終了したら 107 行目の メッセージリスト...
このプログラムではおそらく日本語の表示に端末(shell 端末...
あくまで私の勉強のためのものであるとご理解下さい。 でも、...
終了行:
#norelated
*Linux socket プログラミング/POP3 クライアントプログラム
*目次 [#cdb70484]
#contents
*概要 [#j1c53e91]
こんどは POP3 のクライアントプログラムです。MTA(メール転...
見た目かなり汚くなってしまいましたが、要所要所を変えれば...
*プログラムのイメージ [#j7e59410]
このプログラムで使われる関数のイメージを以下に示します。...
|POP3 サーバ |BGCOLOR(white):|このプログラム|h
|recv()|BGCOLOR(white):USER ID 送信&br;<-----------------...
|recv()|BGCOLOR(white):PASSWORD 送信&br;<----------------...
|recv()|BGCOLOR(white):LIST コマンド送信&br;<------------...
|send()|BGCOLOR(white):LIST受信&br;----------------------...
|recv()|BGCOLOR(white):RETR コマンド送信&br;<------------...
|send()|BGCOLOR(white):メッセージ受信&br;----------------...
*ソースコード [#ne1ca8c4]
CENTER:[[mailp.c>http://github.com/kaizawa/linux-socket/r...
1 /*
2 * POP3 client program
3 * mailp.c
4 * cc mailp.c -lnsl -o mailp
5 */
6
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15
16 #define BUFMAX 256
17 #define PORT_NO 110
18
19 void read_msg();
20 void print_err(char *);
21
22 extern int h_errno;
23 int net;
24 int nbyte;
25 char r_msg[BUFMAX];
26 char s_msg[BUFMAX];
27 char input[6];
28
29 int
30 main(int argc, char *argv[])
31 {
32 struct hostent *host;
33 struct servent *serv;
34 struct sockaddr_in sa;
35 char p_list[] = "LIST\n";
36 char p_user[] = "USER pop_user\n";
37 char p_pass[] = "PASS pop_password\n";
38 char p_quit[] = "QUIT\n";
39
40 if (argc != 2) {
41 printf("Usage: %s hostname\n", argv[0]);
42 exit(1);
43 }
44
45 /*
46 * Check Host name
47 */
48 if ((host = gethostbyname(argv[1])) == NULL){
49 herror("gethostbyname()");
50 close(net);
51 exit(1);
52 }
53
54 memset(&sa,0, sizeof(struct sockaddr_in));
55 memcpy(&sa.sin_addr, host->h_addr, sizeof(str...
56
57 sa.sin_family = AF_INET;
58 sa.sin_port = htons(PORT_NO);
59
60 /*
61 * Make socket
62 */
63 if((net = socket(AF_INET, SOCK_STREAM, 0)) < 0)
64 print_err("socket()");
65
66 /*
67 * Connect to the mail server
68 */
69 if (connect(net, (struct sockaddr *)&sa, size...
70 print_err("connect()");
71
72 /*
73 * Receive connection messages from server
74 */
75 memset(r_msg,0,BUFMAX);
76 if( recv(net,r_msg,BUFMAX,0) < 0)
77 print_err("recv()");
78 printf("%s",r_msg);
79
80 /*
81 * Send user name
82 */
83 nbyte = strlen( p_user );
84 if( send(net,p_user,nbyte,0) < 0)
85 print_err("send()");
86
87 memset(r_msg,0,BUFMAX);
88 if( recv(net,r_msg,BUFMAX,0) < 0)
89 print_err("recv");
90 printf("%s",r_msg);
91
92 /*
93 * Send password
94 */
95 nbyte = strlen(p_pass);
96 if( send(net,p_pass,nbyte,0) < 0 )
97 print_err("send()");
98
99 memset(r_msg,0,BUFMAX);
100 if( recv(net,r_msg,BUFMAX,0) < 0)
101 print_err("recv()");
102 printf("%s",r_msg);
103
104 /*
105 * Request mail list & Select letter number
106 */
107 while(1){ /* loop start */
108 nbyte = strlen( p_list );
109 if( send(net,p_list,nbyte,0) < 0 )
110 print_err("send()");
111 while(1){
112 memset(r_msg,0,BUFMAX);
113 if( recv(net,r_msg,BUFMAX,0) < 0)
114 print_err("recv()");
115 printf("%s",r_msg);
116 if ( strstr( r_msg, "\n.") != NULL) {
117 printf("\n");
118 break;
119 }
120 }
121
122 /*
123 * Enter letter number
124 */
125 printf("Enter the number you want to read...
126 if ( scanf("%5s", input) < 0)
127 print_err("scanf()");
128
129 if ( input[0] == 'q' ) {
130 nbyte = strlen( p_quit );
131 if( send(net,p_quit,nbyte,0) < 0)
132 print_err("send()");
133 memset(r_msg,0,BUFMAX);
134 if( recv(net,r_msg,BUFMAX,0) < 0)
135 print_err("recv()");
136 printf("%s\n",r_msg);
137 /* Normal closure process */
138 if (shutdown(net, 2) < 0)
139 print_err("shutdown()");
140 close(net);
141 exit(0);
142 }
143 if( (isdigit(input[0])) == 0){
144 printf("Input error\n");
145 continue;
146 }
147 read_msg();
148 } /* loop end */
149 }
150
151 /************************************************...
152 * read_msg()
153 *
154 * Retrieve and print email message from the mai...
155 ************************************************...
156 void
157 read_msg()
158 {
159 sprintf(s_msg,"RETR %s\n",input);
160 nbyte = strlen(s_msg);
161 if( send(net,s_msg,nbyte,0) < 0 )
162 print_err("send()");
163 while(1){
164 memset(r_msg,0,BUFMAX);
165 if( recv(net,r_msg,BUFMAX,0) < 0)
166 print_err("recv()");
167 printf("%s",r_msg);
168 if( strstr(r_msg,"\n.") != NULL ){
169 printf("\n");
170 break;
171 }
172 }
173 return;
174 }
175
176 void
177 print_err(char *func)
178 {
179 perror(func);
180 close(net);
181 exit(1);
182 }
ソースファイル [[mailp.c>http://github.com/kaizawa/linux-...
*実行例 [#p046daeb]
このプログラムの実行例を示します。
プログラム名の後に引数として POP3 サーバ名、または IP ア...
% ./mailp mail.example.com
+OK POP3 mail v2001.80 server ready
+OK User name accepted, password please
+OK Mailbox open, 2 messages
+OK Mailbox scan listing follows
1 392
2 395
.
Enter the number you want to read.( q for quit)
1
+OK 392 octets
Return-Path: <root><root@mail.example.com>
Received: (from root@localhost)
by mail.example.com (8.8.7/8.8.7) id AAA21525
for pop_user; Thu, 1 Jul 1999 00:24:05 +0900
Date: Thu, 1 Jul 1999 00:24:05 +0900
From: root
Message-Id: <199906301524.AAA21525@mail.example.com>
To: pop_user@mail.example.com
Subject: test1
X-UIDL: 0beb13dbeab34ae6e3549b3f5ea2872c
Status: RO
This is a test mail from root.
Can you read?
.
+OK 2 messages (787 octets)
1 392
2 395
.
Enter the number you want to read( q for quit)
q
+OK Sayonara
*解説 [#zdd7edf1]
以下にこのプログラムの説明をします。最初にサーバの名前を ...
40 if (argc != 2) {
41 printf("Usage: %s hostname\n", argv[0]);
42 exit(1);
43 }
ここではプログラムの起動時に引数を指定しています。プログ...
48 if ((host = gethostbyname(argv[1])) == NULL){
49 herror("gethostbyname()");
50 close(net);
51 exit(1);
52 }
48 行目ではコマンドの引数であるサーバ名から gethostbyname...
hosts: files dns
たとえは nsswitch.conf が上記のようになっていれば最初に /...
|>|gethostbyname()|h
|概要|ホスト情報入手|
|インクルードファイル | #include <netdb.h>|
|形式| struct hostent *gethostbyname(const char *name);|
|引数| const char *name: サーバ名が格納されている文字配...
|戻り値 |成功時: hostent 構造体にホスト情報をセットし、...
54 memset(&sa,0, sizeof(struct sockaddr_in));
54行目は sockaddr_in 構造体である「sa」に 0 つまり NULL ...
63〜70 行目までは「ポート番号調査」のところで説明したのと...
80 /*
81 * Send user name
82 */
83 nbyte = strlen( p_user );
84 if( send(net,p_user,nbyte,0) < 0)
85 print_err("send()");
86
87 memset(r_msg,0,BUFMAX);
88 if( recv(net,r_msg,BUFMAX,0) < 0)
89 print_err("recv");
90 printf("%s",r_msg);
ここでは send()システムコールを使って p_user(= USER p...
成功するとパスワードを要求するメッセージがサーバから届く...
|>|send()|h
|概要|メッセージの送信|
|インクルードファイル | #include <sys/types.h>&br;#includ...
|形式| int send(int s, const void *msg, int len, unsigne...
|引数 |int s : socket 記述子&br;const void *msg: 送信...
|戻り値 |成功時: 送信されバイト数&br;エラー: -1|
~
|>|recv()|h
|概要|メッセージの受信|
|インクルードファイル | #include <sys/types.h>&br;#includ...
|形式| int recv(int s, void *msg, int len, unsigned int ...
|引数 |int s : socket 記述子&br;const void *msg: 受信...
|戻り値 |成功時: 受信したバイト数&br;エラー: -1|
95〜102 行目も同様です。プログラムの最初で宣言している p_...
107〜148 行目 は while() を使ってループしています。ここで...
104 /*
105 * Request mail list & Select letter number
106 */
107 while(1){ /* loop start */
108 nbyte = strlen( p_list );
109 if( send(net,p_list,nbyte,0) < 0 )
110 print_err("send()");
111 while(1){
112 memset(r_msg,0,BUFMAX);
113 if( recv(net,r_msg,BUFMAX,0) < 0)
114 print_err("recv()");
115 printf("%s",r_msg);
116 if ( strstr( r_msg, "\n.") != NULL) {
117 printf("\n");
118 break;
119 }
120 }
ここでは p_list という文字列を送信しているのはこれまでと...
while() の終了(break)する条件については少々無理があるの...
122 /*
123 * Enter letter number
124 */
125 printf("Enter the number you want to read...
126 if ( scanf("%5s", input) < 0)
127 print_err("scanf()");
128
129 if ( input[0] == 'q' ) {
130 nbyte = strlen( p_quit );
131 if( send(net,p_quit,nbyte,0) < 0)
132 print_err("send()");
133 memset(r_msg,0,BUFMAX);
134 if( recv(net,r_msg,BUFMAX,0) < 0)
135 print_err("recv()");
136 printf("%s\n",r_msg);
137 /* Normal closure process */
138 if (shutdown(net, 2) < 0)
139 print_err("shutdown()");
140 close(net);
141 exit(0);
142 }
143 if( (isdigit(input[0])) == 0){
144 printf("Input error\n");
145 continue;
146 }
126行目では scanf()でユーザからのメール番号の入力を待ちま...
129〜142 行目では、もし「q」という文字が入力された場合サ...
143 if( (isdigit(input[0])) == 0){
144 printf("Input error\n");
145 continue;
146 }
147 read_msg();
「q」以外の文字が入力された場合にはまず、isdigit(3) 関数...
156 void
157 read_msg()
158 {
159 sprintf(s_msg,"RETR %s\n",input);
160 nbyte = strlen(s_msg);
161 if( send(net,s_msg,nbyte,0) < 0 )
162 print_err("send()");
163 while(1){
164 memset(r_msg,0,BUFMAX);
165 if( recv(net,r_msg,BUFMAX,0) < 0)
166 print_err("recv()");
167 printf("%s",r_msg);
168 if( strstr(r_msg,"\n.") != NULL ){
169 printf("\n");
170 break;
171 }
172 }
173 return;
174 }
159 行目では 126 行目でユーザから受け取ったメッセージ番号...
メッセージの表示が終了したら 107 行目の メッセージリスト...
このプログラムではおそらく日本語の表示に端末(shell 端末...
あくまで私の勉強のためのものであるとご理解下さい。 でも、...
ページ名: