ドツボにはまったのでメモ

ソケット通信のプログラムを書くときに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
%s\nSubject
%s\n\n%s\n.\n",from,from,to,subject,data);
#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; }

そうだ.あとこのプログラム中の宛先ポート指定でhtonsを忘れてこれもはまった.