ドツボにはまったのでメモ
ソケット通信のプログラムを書くときにwrite関数を使用する場合,サイズ指定はstrlen関数を使用すること.read関数と同じようにsizeofを使ってしまい,原因不明のバグに半日悩まされたのでメモしておきます.
あとサンプルも書いておこうかな.
C言語でlinux(Vine)でローカルのSMTPサーバに接続しローカルユーザーにメールを送信するサンプルです.多少の不備はご愛嬌で.参考にしたのはhttp://www.site-cooler.com/kwl/perl/smtp.htmで先にperlでサンプルを動かしてから作りました.
#include#include #include #include #include #include #include #define BUF_SIZE 1024 int main(void){ char server = "localhost"; char to = "user@localhost"; char from = "c_program@localhost"; char subject = "test"; char data[] = "hogehoge"; char send_data[BUF_SIZE]; char write_buf[BUF_SIZE]; char read_buf[BUF_SIZE]; char* ptr; int sock; int len; struct sockaddr_in addr; int result; int i; memset(send_data,0,sizeof(send_data)); sprintf(send_data,"X-Mailer:SMTP Sample\nContent-Type:text/plain;charset=iso-2022-jp\nFrom:%s<%s>\nTo #if 0 printf("[%s]\n\n",send_data); #endif sock = socket(AF_INET,SOCK_STREAM,0); if(sock == -1){ perror("socket:"); exit(1); } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port= htons(25); len = sizeof(addr); result = connect(sock,(struct sockaddr*)&addr,len); if(result == -1){ perror("connect:"); exit(1); } memset(read_buf,0,sizeof(read_buf)); memset(write_buf,0,sizeof(write_buf)); read(sock,read_buf,sizeof(read_buf)); #if 0 printf("<-%s",read_buf); #endif ptr = &read_buf[0]; result = 0; len = sizeof(read_buf); do{ if(strncmp(ptr,"220",3) == 0 ){ result = 1; break; } ptr++; }while(result == 1); if(result != 1){ printf("Connect error\n"); close(sock); exit(1); } memset(read_buf,0,sizeof(read_buf)); memset(write_buf,0,sizeof(write_buf)); sprintf(write_buf,"HELO %s\r\n",server); write(sock,write_buf,strlen(write_buf)); read(sock,read_buf,sizeof(read_buf)); #if 0 printf("->%s",write_buf); printf("<-%s",read_buf); #endif ptr = &read_buf[0]; result = 0; do{ if(strncmp(ptr,"250",3) == 0){ result = 1; break; } ptr++; }while(result == 1); if(result != 1){ printf("HELO error\n"); close(sock); exit(1); } memset(read_buf,0,sizeof(read_buf)); memset(write_buf,0,sizeof(write_buf)); sprintf(write_buf,"Mail From:<%s>\r\n",from); write(sock,write_buf,strlen(write_buf)); read(sock,read_buf,sizeof(read_buf)); #if 0 printf("->%s",write_buf); printf("<-%s",read_buf); #endif ptr = &read_buf[0]; result = 0; do{ if(strncmp(ptr,"250",3) == 0){ result = 1; break; } ptr++; }while(result == 1); if(result != 1){ printf("Mail From error\n"); close(sock); exit(1); } memset(read_buf,0,sizeof(read_buf)); memset(write_buf,0,sizeof(write_buf)); sprintf(write_buf,"RCPT To:<%s>\r\n",to); write(sock,write_buf,strlen(write_buf)); read(sock,read_buf,sizeof(read_buf)); #if 0 printf("->%s",write_buf); printf("<-%s",read_buf); #endif ptr = &read_buf[0]; result = 0; do{ if(strncmp(ptr,"250",3) == 0 || strncmp(ptr,"251",3) == 0){ result = 1; break; } ptr++; }while(result == 1); if(result != 1){ printf("RCPT error\n"); close(sock); exit(1); } memset(read_buf,0,sizeof(read_buf)); memset(write_buf,0,sizeof(write_buf)); sprintf(write_buf,"DATA\r\n"); write(sock,write_buf,strlen(write_buf)); read(sock,read_buf,sizeof(read_buf)); #if 0 printf("->%s",write_buf); printf("<-%s",read_buf); #endif ptr = &read_buf[0]; result = 0; do{ if(strncmp(ptr,"354",3) == 0){ result = 1; break; } ptr++; }while(result == 1); if(result != 1){ printf("DATA error\n"); close(sock); exit(1); } memset(read_buf,0,sizeof(read_buf)); memset(write_buf,0,sizeof(write_buf)); sprintf(write_buf,"%s",send_data); write(sock,write_buf,strlen(write_buf)); read(sock,read_buf,sizeof(read_buf)); #if 0 printf("->%s",write_buf); printf("<-%s",read_buf); #endif ptr = &read_buf[0]; result = 0; do{ if(strncmp(ptr,"250",3) == 0){ result = 1; break; } ptr++; }while(result == 1); if(result != 1){ printf("Send error\n"); close(sock); exit(1); } sprintf(write_buf,"QUIT\r\n"); write(sock,write_buf,strlen(write_buf)); printf("program end\n"); return 0; }
- %s\nSubject
- %s\n\n%s\n.\n",from,from,to,subject,data);
そうだ.あとこのプログラム中の宛先ポート指定でhtonsを忘れてこれもはまった.