• 締切済み

C言語で作成するチャットについて

LinuxでC言語のチャットプログラムを作成しています。プログラムを作ってみましたがうまく動きません。悪い個所が分からないのでお力を貸して頂きたいです課題の提出が迫っているので、よろしくお願いいたします。 <server> #include省略 #define PORT 5320 char *show_ip(char *ip_address); int main(void){ int soc, acc, size, child[3],width,i,count,pos,ret; char buffer[80]; struct sockaddr_in client, server; struct sockaddr_storage from; struct hostent *server_host; socklen_t len; fd_set mask; char host_name[257]; int temp; memset(host_name, 0, sizeof(host_name)); gethostname(host_name, 256); server_host = gethostbyname(host_name); printf("\n-------- informations of server ----------\n"); printf("Host name:%s\n", host_name); printf("IP = %s\n", show_ip(server_host->h_addr)); printf("\n\n"); soc = socket(AF_INET, SOCK_STREAM, 0); memset((char *)&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(PORT); bind(soc, (struct sockaddr *)&server, sizeof(server)); size = sizeof(client); listen(soc, 5); for (i = 0; i < 3; i++){ child[i] = -1; } for (;;) { FD_ZERO(&mask); FD_SET(soc, &mask); for (i = 0; i < 3; i++) { if (child[i] != -1){ FD_SET(child[i], &mask); if(child[i]+1 > width){ width = child[i]+1; } } } switch(select(soc+1, (fd_set *) &mask, NULL, NULL, NULL)) { case -1: perror("select"); break; case 0: break; default: if (FD_ISSET(soc, &mask)){ len = (socklen_t) sizeof(from); if((acc = accept(child[i], (struct sockaddr *)&from, &len)) == -1){ if(errno != EINTR){ perror("accept"); } }else{ if(child[0]&&child[1]&&child[2]!=-1){ fprintf(stderr,"child is full : cannot accept\n"); close(acc); }else{ if(child[0] == -1){ child[0] = acc; }else if(child[1] == -1){ child[1] = acc; }else{ child[2] = acc; } } } } for(i=0;i<3;i++){ if(child[i]!=-1){ if(FD_ISSET(child[i],&mask)){ memset(buffer, '\0', sizeof(buffer)); recv(child[i], buffer, 80, 0); printf("%s> ", show_ip((char *)&client.sin_addr)); printf("%s", buffer); if(strncmp(buffer, "exit", 4) == 0) break; for(i=0;i<3;i++) { send(child[i],show_ip((char *)&client.sin_addr),80,0); send(child[i],buffer,80,0); close(child[i]); } (void) close(child[i]); child[i] = -1; } } break; } } } } char *show_ip(char *ip_address){ static char ip[7]; char ipnum[4]; bcopy(ip_address, ipnum, 4); sprintf(ip, "%u.%u.%u.%u",(unsigned char)ipnum[0], (unsigned char)ipnum[1], (unsigned char)ipnum[2],(unsigned char)ipnum[3]); return ip; } <client> #include省略 #define STDIN_FD 0 #define PORT 5320 int select_func(int sockfd); void err_func(char *msg){ perror(msg); exit(EXIT_FAILURE); } int main(int argc, char **argv){ int sockfd, len; char buf[BUFSIZ]; struct sockaddr_in serv; unsigned short port; if(argc != 3){ printf("usage: progname serv_ip serv_port\n"); exit(EXIT_FAILURE); } if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) err_func("socket"); serv.sin_family = PF_INET; port = (unsigned short)atoi(argv[2]); serv.sin_port = htons(port); inet_aton(argv[1], &(serv.sin_addr)); if(connect(sockfd, (struct sockaddr *)&serv, sizeof(struct sockaddr_in)) < 0) err_func("connect"); do{ if(select_func(sockfd) == 0){ len = recv(sockfd, buf, BUFSIZ, 0); buf[len] = '\0'; printf("-> %s\n", buf); }else{ len = read(STDIN_FD, buf, BUFSIZ); len = send(sockfd, buf, len, 0); } }while(strncmp(buf, "EXIT\r\n", 6) != 0 && strncmp(buf, "EXIT\n", 5) != 0); close(sockfd); return 0; } int select_func(int sockfd){ fd_set rfds; FD_ZERO(&rfds); FD_SET(sockfd, &rfds); FD_SET(STDIN_FD, &rfds); if(select(sockfd+1, &rfds, NULL, NULL, NULL) < 0) err_func("select"); if(FD_ISSET(STDIN_FD, &rfds)) return STDIN_FD; return sockfd; }

みんなの回答

回答No.2

tsuduki123 さんによる指摘の他に気になったこととして、recvでのデータ受信を適切に行っていないように思われます。おそらく、1回のsendで送信されたデータは必ず1回のrecvで受信できる、という仮定のもとにプログラムを作成したのではないでしょうか。 このプログラムで使用しているTCPプロトコルでは、データがどこで切れるのかは保証されません。1回のsendで送信したデータが複数回のrecvに分割されて受信することもあれば、複数回のsendで送信されたものがまとめて1回のrecvで受信されることもあり得ます。 極端な例では、送信側で200バイトのデータをsendしたら受信側では1バイトのデータを200回recvすることになった、ということも可能性としてはゼロではないわけで、プログラムもそれを想定して作成する必要があります。 詳細については以下のURLを参照してください。 Windows Socket向けの解説ですが、LinuxでTCPソケットを使う場合も同じことが当てはまります。 Winsock 中級者向けの議論 3.4 - TCPのようなストリームプロトコルで、パケット単位の処理を強制するための正しい方法は? http://www.kt.rim.or.jp/~ksk/wskfaq-ja/intermediate.html#packetscheme TCP を有効に使うために http://www.kt.rim.or.jp/~ksk/wskfaq-ja/articles/effective-tcp.html ザ・間違いリスト 20.ストリームソケットで、メッセージフレームの区 切りが保持されると仮定すること http://www.kt.rim.or.jp/~ksk/wskfaq-ja/articles/lame-list.html#item20

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

うまく動かない内容がわからないので ロジックじゃなくてぱっと見て、直した方がいいところの指摘だけ。。 server側 1. socket作成の時はgetadrinfo(3)を利用しましょう。こっちの方が簡単だし、都合いいこと多いです。 2. setsockopt()で SO_REUSEADDR を設定してあげた方がいいんじゃないかと思います。 3. select(2)に指定する最初の引数は待ち受けるfdの最大+1です。 acceptのところで最大を保存して利用するようにしましょう 4. acceptに指定する最初の引数はlistenしてbindで待ち受けているソケットです。 5. fd系は-1が帰ってきたとき、errnoがEINTRとEWOULDBLOCKかチェックしていずれかなら正常系でcontinueさせます。 6. チャットなら、クライアントからrecvしたバイト数を保持してsendするときに利用しないとおかしな文字列を送信することになると思います。 7. static char ip[7]; 桁がたりないんじゃないかな 8. サーバーからクライアントへ送信するとき、送信元のクライアントは除外してあげた方がいい気がする client側 1. こちらもgetadrinfo(3)を利用しましょう。 2. サーバーから受信するまでサーバー送信できない気がする selectの部分をもっと丁寧に

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • TCP/IP通信型大文字・小文字変換プログラム

    TCP/IP通信型大文字・小文字変換プログラムを作りたいです。 しかし、うまく2つのプログラムが接続されません。 恐らく、IPアドレスやホスト名の問題だと思います。 超初心者でそこのところをあまり理解していません。 どなたかプログラムの補足をお願いします。 概要は ・クライアント キーボードから文字列を入力し、サーバーに送信。 サーバーから送信された文字列を画面に出力。 ・サーバー クライアントから送信された文字列に対し、 大文字は小文字に、小文字は大文字に変換して返す。 クライアント側プログラム #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #define SOCK_NAME "./socket" int main() { struct sockaddr_in saddr; int soc; char buf[1024]; if ( (soc =socket(AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=inet_addr("192.168.1.1"); saddr.sin_port=htons(1357); if(connect(soc, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("connect"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", soc); while(fgets(buf, 1024, stdin)){ if(buf[strlen(buf) -1] == "\n") buf[strlen(buf) -1] = "\0"; write(soc, buf, 1024); read(soc, buf, 1024); fprintf(stdout, "%s\n", buf); } close(soc); return 0; } サーバー側プログラム #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define SOCK_NAME "./socket" int main() { int i; int fd1, fd2; struct sockaddr_in saddr; struct sockaddr_in caddr; int len; int ret; char buf[1024]; if((fd1 =socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_port=htons(1357); unlink(SOCK_NAME); if(bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } if(listen(fd1,5) < 0 ) { perror("listen"); exit(1); } while(1){ len = sizeof(caddr); if((fd2 = accept(fd1, (struct sockaddr *)&caddr, &len)) < 0){ perror("accept"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", fd2); while((ret = read(fd2, buf, 1024)) > 0 ){ fprintf(stderr, "read: &s\n", buf); for(i=0; i<ret; i++) if(islower(buf[i])) buf[i] = toupper(buf[i]); if(isupper(buf[i])) buf[i] = tolower(buf[i]); fprintf(stderr, "write: %s\n", buf); write(fd2, buf, 1024); } close(fd2); } close(fd1); return 0; }

  • c言語のチャットプログラムのsendとrecv

    現在、複数のクライアントからサーバーにメッセージを送りサーバーからクライアントにメッセージを送るというものを作成しているのですが、クライアントからサーバーにはメッセージを送れるのですが、サーバー側からクライアント1人にしか送れず、クライアント全員にメッセージを送信できませんので、よろしければアドバイスをお願いします サーバーのプログラム インクルード省略 #define BUF_LEN 256 typedef struct CLIENT_INFO { char hostname[BUF_LEN]; char ipaddr[BUF_LEN]; int port; time_t last_access; } CLIENT_INFO; CLIENT_INFO client_info[FD_SETSIZE]; int listening_socket; struct sockaddr_in sn; int accept_new_client(int sock){ int len; int new_socket; struct hostent *peer_host; struct sockaddr_in peer_sin; len = sizeof(sn); new_socket = accept(listening_socket, (struct sockaddr *)&sn, &len); if ( new_socket == -1 ){ perror("accept"); exit(1); } if ( new_socket > FD_SETSIZE-1 ){ return -1; } len = sizeof(peer_sin); getpeername(new_socket, (struct sockaddr *)&peer_sin, &len); peer_host = gethostbyaddr((char *)&peer_sin.sin_addr.s_addr, sizeof(peer_sin.sin_addr), AF_INET); strncpy(client_info[new_socket].hostname, peer_host->h_name, sizeof client_info[new_socket].hostname); strncpy(client_info[new_socket].ipaddr, inet_ntoa(peer_sin.sin_addr), sizeof client_info[new_socket].ipaddr); client_info[new_socket].port = ntohs(peer_sin.sin_port); time(&client_info[new_socket].last_access); printf("接続: %s (%s) ポート %d ディスクリプタ %d 番\n", client_info[new_socket].hostname, client_info[new_socket].ipaddr, client_info[new_socket].port, new_socket); return new_socket; } int read_and_reply(int sock){ int read_size; char buf[BUF_LEN]; read_size = read(sock, buf, sizeof(buf)-1); if ( read_size == 0 || read_size == -1 ){ printf("%s (%s) ポート %d ディスクリプタ %d 番からの接続が切れました。\n", client_info[sock].hostname, client_info[sock].ipaddr, client_info[sock].port, sock); close(sock); client_info[sock].last_access = 0; } else { buf[read_size] = '\0'; printf("%s (%s) ポート %d ディスクリプタ %d 番からのメッセージ: %s", client_info[sock].hostname, client_info[sock].ipaddr, client_info[sock].port, sock, buf); write(sock, buf, strlen(buf)); time(&client_info[sock].last_access); } return read_size; } int main(){ fd_set target_fds; fd_set org_target_fds; int sock_optval = 1; int port = 5000;    listening_socket = socket(AF_INET, SOCK_STREAM, 0); if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &sock_optval, sizeof(sock_optval)) == -1 ){ perror("setsockopt"); exit(1); }  sn.sin_family = AF_INET; sn.sin_port = htons(port); sn.sin_addr.s_addr = htonl(INADDR_ANY); if ( bind(listening_socket, (struct sockaddr *)&sn, sizeof(sn)) < 0 ){ perror("bind"); exit(1); }   if ( listen(listening_socket, SOMAXCONN) == -1 ){ perror("listen"); exit(1); printf("ポート %d を見張ります。\n", port);   FD_ZERO(&org_target_fds); FD_SET(listening_socket, &org_target_fds);   while (1){ int i; time_t now_time; struct timeval waitval; waitval.tv_sec = 2; waitval.tv_usec = 500;  memcpy(&target_fds, &org_target_fds, sizeof(org_target_fds));  select(FD_SETSIZE, &target_fds, NULL, NULL, &waitval);  for ( i=0 ; i<FD_SETSIZE ; i++ ) { if ( FD_ISSET(i, &target_fds) ) { printf("ディスクリプタ %d 番が読み込み可能です。\n", i); if ( i == listening_socket ) { int new_sock; new_sock = accept_new_client(i); if ( new_sock != -1 ) { FD_SET(new_sock, &org_target_fds); } } else {int read_size;  read_size = read_size; read_size = read_and_reply(i); if ( read_size == -1 || read_size == 0 ) { FD_CLR(i, &org_target_fds); } } } } time(&now_time); for ( i=0 ; i<FD_SETSIZE ; i++){ if ( ! FD_ISSET(i, &org_target_fds) ) continue; if ( i == listening_socket ) continue; if ( now_time-60 > client_info[i].last_access ) { close(i); FD_CLR(i, &org_target_fds); } } } close(listening_socket); FD_CLR(i, &org_target_fds); } }

  • TCP/IP通信型電話番号検索プログラムを作りたいです。

    TCP/IP通信型電話番号検索プログラムを作りたいです。 クライアントは以下のようで大丈夫みたいなのですが、サーバの方を修正しなければなりません。 この質問で「TCP/IP通信型大文字・小文字変換プログラム」を発見しました。 サーバー側プログラム #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define SOCK_NAME "./socket" int main() { int i; int fd1, fd2; struct sockaddr_in saddr; struct sockaddr_in caddr; int len; int ret; char buf[1024]; if((fd1 =socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_port=htons(1357); unlink(SOCK_NAME); if(bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } if(listen(fd1,5) < 0 ) { perror("listen"); exit(1); } while(1){ len = sizeof(caddr); if((fd2 = accept(fd1, (struct sockaddr *)&caddr, &len)) < 0){ perror("accept"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", fd2); while((ret = read(fd2, buf, 1024)) > 0 ){ fprintf(stderr, "read: &s\n", buf); for(i=0; i<ret; i++) if(islower(buf[i])) buf[i] = toupper(buf[i]); if(isupper(buf[i])) buf[i] = tolower(buf[i]); fprintf(stderr, "write: %s\n", buf); write(fd2, buf, 1024); } close(fd2); } close(fd1); return 0; } 先生によると、クライアントは同じもので良いそうです。 誰か、助けて下さい。

  • チャットプログラムでのselectの使い方について

    linux開発環境でC言語を用いて1対5程度のチャットプログラムを作成しています。クライアントから送信された内容はサーバに表示されるのですが、この内容を他のクライアントにも表示したいです。そこでselect関数を用いたいのですが、どこにどのようなコードで挿入すればよいかわかりません。以下にプログラムを載せるので、できれば詳しいコードで回答をよろしくお願いいたします。 サーバプログラム #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/wait.h> #include <unistd.h> #include <signal.h> #include <netdb.h> #define PORT 5320 void kill_zombie_process(int sig); void close_process(int unused); char *show_ip(char *ip_address); int main(void) { int soc, acc, size; char buffer[80]; struct sockaddr_in client, server; struct hostent *server_host; pid_t pid; char host_name[257]; int temp; memset(host_name, 0, sizeof(host_name)); gethostname(host_name, 256); server_host = gethostbyname(host_name); printf("\n-------- informations of server ----------\n"); printf("Host name:%s\n", host_name); printf("IP = %s\n", show_ip(server_host->h_addr)); printf("\n\n"); soc = socket(AF_INET, SOCK_STREAM, 0); memset((char *)&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(PORT); bind(soc, (struct sockaddr *)&server, sizeof(server)); size = sizeof(client); listen(soc, 5); signal(SIGINT, close_process); signal(SIGCHLD, kill_zombie_process); while(1) { acc = accept(soc, (struct sockaddr *)&client, &size); pid = fork(); if(pid == 0) { close(soc); while(1) { memset(buffer, '\0', sizeof(buffer)); recv(acc, buffer, 80, 0); printf("%s> ", show_ip((char *)&client.sin_addr)); printf("%s", buffer); if(strncmp(buffer, "exit", 4) == 0) break; } close(acc); exit(0); } else { close(acc); } } return 0; } void kill_zombie_process(int sig) { while(waitpid(-1, NULL, WNOHANG) > 0); signal(SIGCHLD, kill_zombie_process); } void close_process(int unused) { exit(0); } char *show_ip(char *ip_address) { static char ip[7]; char ipnum[4]; bcopy(ip_address, ipnum, 4); sprintf(ip, "%u.%u.%u.%u",(unsigned char)ipnum[0], (unsigned char)ipnum[1], (unsigned char)ipnum[2],(unsigned char)ipnum[3]); return ip; } クライアントプログラム #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #define PORT 5320 int main(int argc, char *argv[]) { int soc; char message[80],ip_address[16]; struct sockaddr_in server; if(argc == 1) { printf("引数にIPアドレスが必要です/n"); exit(0); } strcpy(ip_address,argv[1]); soc = socket(AF_INET,SOCK_STREAM,0); memset((char *)&server,0,sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = inet_addr(ip_address); connect(soc,(struct sockaddr *)&server,sizeof(server)); while(1) { printf("メッセージを入力してください:"); fgets(message,80,stdin); send(soc,message,strlen(message),0); if(strncmp(message,"exit",4) == 0)break; } close(soc); return 0; }

  • UDP通信について

    UDP通信で困っています。 TCP/IP通信はすぐにうまくいったのですが、 UDPの簡単なサンプルがちゃんと動きません。 間違いがあればご指摘ください。 よろしくお願いします。 (クライアント側ソース int sock; struct sockaddr_in din; memset(&din, 0, sizeof(din)); din.sin_port = htons(50050); din.sin_family = AF_INET; din.sin_addr.s_addr = inet_addr("サーバーIP"); sock = socket(AF_INET, SOCK_DGRAM, 0); int buf = 12345; sendto(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&din,sizeof(struct sockaddr_in)); (サーバー側ソース int sock; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_DGRAM, 0); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(50050); sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { return(1); } struct sockaddr_in fromaddr; socklen_t len = sizeof(struct sockaddr_in); int buf; recvfrom(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&fromaddr,&len); printf("recv:%d\n",buf);

  • HTTPクライアントの作成について

    下のc言語で書かれたプログラムソースは、とあるHPにあったものです。受信して表示するだけですが、実際にコンパイルもでき動作も確認しています。仕組みも大体は理解しているつもりです。このプログラムを改造して、リンクのURLの一覧のみ表示させるには、どのように改造すればよいのでしょうか?それとも、根本的に仕組みが異なるのでしょうか?詳しくご指導いただけるとありがたいです。そのHPのURLものせておきます。よろしくお願いします。 URL:http://x68000.q-e-d.net/~68user/net/c-http-1.html ※includeは省略しています。 #define BUF_LEN 256 /*バッファのサイズ */ int main(int argc, char *argv[]){ int s; /*ソケットのためのファイルディスクリプタ */ struct hostent *servhost; /*ホスト名と IP アドレスを扱うための構造体 */ struct sockaddr_in server; /*ソケットを扱うための構造体 */ struct servent *service; /*サービス (http など) を扱うための構造体 */ char send_buf[BUF_LEN]; /* サーバに送るHTTP プロトコル用バッファ */ char host[BUF_LEN] = "localhost"; /*接続するホスト名 */ char path[BUF_LEN] = "/"; /*要求するパス */ unsigned short port = 0; /*接続するポート番号 */ if ( argc > 1 ){ /*URLが指定されていたら */ char host_path[BUF_LEN]; if ( strlen(argv[1]) > BUF_LEN -1 ){ fprintf(stderr, "URL が長すぎます。\n"); return 1; } /*http:// から始まる文字列で */ /*sscanf が成功して */ /*http:// の後に何か文字列が存在するなら */ if ( strstr(argv[1], "http://") && sscanf(argv[1], "http://%s", h ost_path) && strcmp(argv[1], "http://") ){ char *p; p = strchr(host_path, '/'); /* ホストとパスの区切り "/" を調べる */ if ( p != NULL ){ strcpy(path, p);/*"/"以降の文字列を path にコピー */ *p = '\0'; strcpy(host, host_path ); /*"/"より前の文字列を host にコピー */ } else {/*"/"がないなら=http://host という引数なら */ strcpy(host, host_path); /*文字列全体を host にコピー */ } p = strchr(host, ':'); /*ホスト名の部分に ":" が含まれていたら */ if ( p != NULL ){ port = atoi(p+1); /*ポート番号を取得 */ if ( port <= 0 ){ /*数字でない (atoi が失敗)か、0だったら */ port = 80; /*ポート番号は 80 に決め打ち */ } *p = '\0'; } } else { fprintf(stderr, "URLはhttp://host/path の形式で指定してください。\n"); return 1; } } printf("http://%s%s を取得します。\n\n",host, path); /* ホストの情報(IPアドレスなど)を取得 */ servhost = gethostbyname(host); if ( servhost == NULL ){ fprintf(stderr, "[%s] から IPアドレスへの変換に失敗しました。\n", host); return 0; } bzero(&server, sizeof(server));  /* 構造体をゼロクリア */ server.sin_family = AF_INET; /* IPアドレスを示す構造体をコピー */ bcopy(servhost->h_addr, &server.sin_add r,servhost->h_length); if ( port != 0 ){/* 引数でポート番号が指定されていたら */ server.sin_port = htons(port); } else {/* そうでないなら getservbyname でポート番号を取得 */ service = getservbyname("http", "tcp"); if ( service != NULL ){  /* 成功したらポート番号をコピー */ server.sin_port = service->s_port; } else { /* 失敗したら 80 番に決め打ち */ server.sin_port = htons(80); } } /* ソケット生成 */ if ( ( s = socket(AF_INET, SOCK_STREAM, 0) ) < 0 ){ fprintf(stderr, "ソケットの生成に失敗しました。\n"); return 1; } /* サーバに接続 */ if ( connect(s, (struct sockaddr *)&ser ver, sizeof(server)) == -1 ){ fprintf(stderr, "connectに失敗しました。\n"); return 1; } /* HTTP プロトコル生成 & サーバに送信 */ sprintf(send_buf, "GET %s HTTP/1.0\r\n" , path); write(s, send_buf, strlen(send_buf)); sprintf(send_buf, "Host: %s:%d\r\n", ho st, port); write(s, send_buf, strlen(send_buf)); sprintf(send_buf, "\r\n"); write(s, send_buf, strlen(send_buf)); /* あとは受信して、表示するだけ */ while (1){ char buf[BUF_LEN]; int read_size; read_size = read(s, buf, BUF_LEN); if ( read_size > 0 ){ write(1, buf, read_size); } else { break; } } /* 後始末 */ close(s); return 0; }

  • C言語のsendとrecv

    C言語でクライアントとサーバのプログラムを作りたいのですが、かなりの初心者なので、とりあえず練習用として、クライアント側に整数を入力すると、サーバ側でその整数を二乗して、結果をクライアント側に返すという簡単なプログラムを作ろうと思いました。 ソケットの作成、通信ドメインの指定等は、参考書を見ながら(というか、ほとんど丸写しみたいな感じなんですが…)、なんとかできたんですが、sendとrecvで整数を送受信するにはどうすればいいのかが分かりません。 私が持っている参考書には、 int send(SOCKETS const char FAR *buf int len int flags); int recv(SOCKETS char FAR *buf int len int flags); とあるのですが、const char FAR *buf、int len、char FAR *bufのところがよく分からないのです。 例えば、a=1000を送信したい場合、aはchar型ではないのでsendでは送れないのですか? ほんと初心者ですいませんが、どなたか教えてください。 よろしくお願いします。

  • C言語で分からない部分がいくつかあります。

    長文になります。 市のデータ(cities.txt)を対象として、以下の各機能を持ったプログラムを作成しました。 1.情報の登録と一覧表示 2.情報の削除 3.cities.txt からの情報の読み込み 4.citiesDB.txtへのリスト内容の書き出し 5.人口でソート #include <stdio.h> #include <stdlib.h> #include <string.h> #define STRLEN 32 #define BUF_LEN 128 #define CITYDB_R_FILE "cities.txt" // 読み込み用ファイル #define CITYDB_W_FILE "citiesDB.txt" // 書き出し用ファイル struct cities{ char pref[STRLEN]; char city[STRLEN]; int popl; float area; float dens; char founded[STRLEN]; struct cities *next; }; struct cities *root=NULL; // rootへのポインタは大域変数として定義 void *mymalloc(size_t sz){ void *p = (void *)malloc(sz); if(p == NULL){ fprintf(stderr,"ERR: Can't malloc memory %d bytes.",(int)sz); exit(1); } memset(p,0,sz); return p; } void showCity(struct cities *c, FILE *fp){ fprintf(fp,"%s\t%s\t%d\t%.2f\t%.2f\t%s\n", c->pref, c->city, c->popl, c->area, c->dens, c->founded); } struct cities *genNewCityCell(char *pref, char *city, int popl, float area, float dens, char *founded ){ struct cities *c; c = mymalloc(sizeof(struct cities)); // メモリを確保した c に対して、値を代入する return c; } void showList(FILE *fp){ struct cities *cur= root; while(cur != NULL){ showCity(cur,fp); cur = cur->next; } } void saveList(){ // 書き込み用のファイルを開き、そのファイルポインタ fp に対して、 // showList(fp) を呼ぶ。 void showList() は12行上で定義している printf("File saved to %s\n",CITYDB_W_FILE); } struct cities *line2City(char *buf){ struct cities *c=NULL; int popl; char pref[STRLEN], city[STRLEN], founded[STRLEN]; float area, dens; sscanf(buf, "%s %s %d %f %f %s", pref, city, &popl, &area, &dens, founded); c = genNewCityCell(pref,city,popl,area,dens,founded); return c; } void addCity(struct cities *c){ struct cities **cur= &root; /* rootから順にたどって,末尾に挿入する */ } void inputStr(char *buf,int len){ fgets(buf,len,stdin); buf[strlen(buf)-1]='\0'; } void addNewCity(){ char buf[BUF_LEN] = ""; struct cities *c; while(strlen(buf)<=0){ printf("Input one line:\n"); inputStr(buf, BUF_LEN); } if(strncmp(buf, "Prefecture", 10) == 0) return; c = line2City(buf); addCity(c); } void deleteCityFromList(char *delcity){ /* 順にたどり,当該項目を削除する. addCity() も同様. */ } void deleteCity(){ char buf[STRLEN]; showList(stdout); printf("Select Delete City Name:"); inputStr(buf, STRLEN); deleteCityFromList(buf); } void readListFILE(FILE *fp){ char buf[BUF_LEN]; struct cities *c; while( fgets(buf,BUF_LEN,fp) != NULL){ if(strncmp(buf, "Prefecture", 10) == 0) continue; c = line2City(buf); if(c != NULL) addCity(c); } } void readList(){ /* ファイルCITYDB_R_FILEを読み取り用で開く ファイルが開けない場合のエラー処理 readListFILE(fp); ファイルをクローズ */ printf("File loaded\n"); } void insertCityByPopl(struct cities *sc){ struct cities **cur= &root; /* 順にたどり、挿入すべき箇所に sc を挿入 */ } void sortList(){ struct cities *cur,*fr; cur = root; root = NULL; while(cur != NULL){ insertCityByPopl(genNewCityCell(cur->pref, cur->city, cur->popl, cur->area, cur->dens, cur->founded)); fr = cur; cur = cur->next; free(fr); } showList(stdout); } int main(int argc, char *argv[]){ char buf[BUF_LEN]; while(1){ printf("Menu(a:add, d:delete, l:list, s:sort, w:write file, r:read file q:quit):\n"); fgets(buf,BUF_LEN,stdin); switch(buf[0]){ case 'a': addNewCity(); break; case 'd': deleteCity(); break; case 'l': showList(stdout); break; case 's': sortList(); break; case 'w': saveList(); break; case 'r': readList(); break; case 'q': exit(0); break; } } } ただ、コメントのある部分の関数が完成できません・・・・ どなたか教えてください。

  • C言語の課題で困っています;

    C言語の課題で困ってます; 学校の課題で、キーボードから文字を入力する(最大80文字)。入力された文字列と、入力した文字列を逆順にした文字列を表示する。(malloc,freeを使って作成して下さい) ヒントで #invlude <stdio.h> void main(void){ char *buf; //入力文字列用 char *seq; //入力文字列用コピー用 char *rev; //逆順文字列用 int lec, i; buf =(char*)malloc(81); printf("文字列を入力:"); scanf("%s"buf ); for(i = 0; buf[i] ??? '\0'; i++){ } Ien = i; /* lenに文字列の長さが入る */ seq = ???(??? + 1); /* len+1文字文確保*/ for(i = 0; ???; i++){ seq[0] = buf[0]; } free(buf); rey = ???(len + 1); for(i = 0; < len; i++){ rev[len - i - 1] = seq[i]; } ren[i] ~ '\0'; printd("入力文字列 : %s\n",sep); でたんですが、全然分からなくて足りない部分の答えを教えてもらえると助かります;

  • C言語の使い方を教えてください。-C言語入門者

    C言語のプログラムの処理の対象となるファイルはどこに保存したらよいのでしょうか?たとえば下記のプログラムで #include <stdio.h> #include <stdlib.h> #include <string.h> void main(void) { char *line[100], *buf; int i = 0, len, lines; FILE *fp; fp = fopen("textfile.txt", "r"); buf = calloc(128, sizeof(char)); while (i < 100 && fgets(buf, 128, fp) != NULL) { len = strlen(buf); line[i] = calloc(len + 1, sizeof(char)); strcpy(line[i], buf); i++; } fclose(fp); lines = ((i <= 100) ? i :100); free(buf); for(i = 0; i < lines; i++) printf("%s", line[i]); for(i = 0; i < lines; i++) free(line[i]); } で [textfile.txt]という名のファイルをマイドキュメントやコンパイラーを保存しているのと同じ領域に保存してコンパイラーを実行しても所要の結果が得られません。テキストにはプログラムの作り方しか書いてありません。

このQ&Aのポイント
  • 突然印刷できなくなり、印刷ジョブのキューが消える問題についてご相談です。
  • ドライバの再インストールやファームウェアのバージョンアップなどの対策を試しましたが解決しませんでした。
  • 購入した製品の交換を検討している状況です。
回答を見る

専門家に質問してみよう