亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: 一個基于tcp的socket代碼,友們幫忙指點一下問題 [打印本頁]

作者: 嵌入式教父    時間: 2012-07-29 21:19
標(biāo)題: 一個基于tcp的socket代碼,友們幫忙指點一下問題
下面代碼是局域網(wǎng)server同client相互發(fā)送數(shù)據(jù)代碼,代碼問題是為什么只能互相發(fā)送一次數(shù)據(jù),再發(fā)送,對方就收不到了,求教!
代碼如下:
/******* 服務(wù)器程序  (server.c) ************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int
main (int argc, char *argv[])
{
  int sockfd, new_fd, pid, nbytes;
  struct sockaddr_in server_addr;
  struct sockaddr_in client_addr;
  int sin_size, portnumber;
  char buffer[1024 * 1024] = { 0 };
  char hello[1024 * 1024] = { 0 };

  if (argc != 2)
    {
      fprintf (stderr, "Usage:%s portnumber\a\n", argv[0]);
      exit (1);
    }

  if ((portnumber = atoi (argv[1])) < 0)
    {
      perror ("atoi() error\n");
      exit (1);
    }

  /* 服務(wù)器端開始建立socket描述符 */
  if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {
      perror ("socket() error\n");
      exit (1);
    }

  /* 服務(wù)器端填充 sockaddr結(jié)構(gòu)  */
  bzero (&server_addr, sizeof (struct sockaddr_in));
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  server_addr.sin_port = htons (portnumber);

  /* 捆綁sockfd描述符  */
  if (bind
      (sockfd, (struct sockaddr *) (&server_addr),
       sizeof (struct sockaddr)) == -1)
    {
      perror ("bind() error\n");
      exit (1);
    }

  /* 監(jiān)聽sockfd描述符  */
  if (listen (sockfd, 5) == -1)
    {
      perror ("listen() error\n");
      exit (1);
    }

  while (1)
    {

      /* 服務(wù)器阻塞,直到客戶程序建立連接  */
      sin_size = sizeof (struct sockaddr_in);
      if ((new_fd =
           accept (sockfd, (struct sockaddr *) (&client_addr),
                   &sin_size)) == -1)
        {
          perror ("accept() error\n");
          exit (1);
        }

      fprintf (stderr, "Server get connection from %s\n",
               inet_ntoa (client_addr.sin_addr));
      if ((pid = fork ()) < 0)
        {
          perror ("fork() error\n");
          exit (1);
        }
      else if (pid == 0)
        {
          if ((nbytes = read (new_fd, buffer, sizeof (buffer))) == -1)
            {
              perror ("read() error\n");
              exit (1);
            }
          buffer[nbytes] = '\0';
          fputs (buffer, stdout);
          close (new_fd);
        }
      else
        {
          fgets (hello, sizeof (hello), stdin);
          if (write (new_fd, hello, strlen (hello)) == -1)
            {
              perror ("write() error\n");
              exit (1);
            }

          /* 這個通訊已經(jīng)結(jié)束     */
          close (new_fd);
        }
    }
  close (sockfd);
  exit (0);
}

=================================================================================

/******* 客戶端程序  client.c ************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netdb.h>
int
main (int argc, char *argv[])
{
  int sockfd, pid;
  char buffer[1024 * 1024] = { 0 };
  char hello[1024 * 1024] = { 0 };
  struct sockaddr_in server_addr;
  struct hostent *host;
  int portnumber, nbytes;

  if (argc != 3)
    {
      fprintf (stderr, "Usage:%s hostname portnumber\a\n", argv[0]);
      exit (1);
    }

  if ((host = gethostbyname (argv[1])) == NULL)
    {
      perror ("gethostbyname() error\n");
      exit (1);
    }

  if ((portnumber = atoi (argv[2])) < 0)
    {
      perror ("atoi() error\n");
      exit (1);
    }

  /* 客戶程序開始建立 sockfd描述符  */
  if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {
      perror ("socket() error\n");
      exit (1);
    }

  /* 客戶程序填充服務(wù)端的資料       */
  bzero (&server_addr, sizeof (server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons (portnumber);
  server_addr.sin_addr = *((struct in_addr *) host->h_addr);

  /* 客戶程序發(fā)起連接請求         */
  if (connect
      (sockfd, (struct sockaddr *) (&server_addr),
       sizeof (struct sockaddr)) < 0)
    {
      perror ("connect() error\n");
      exit (1);
    }
  /* 連接成功了           */
  if ((pid = fork ()) < 0)
    {
      perror ("fork() error\n");
    }
  else if (pid > 0)
    {

      while (1)
        {
          nbytes = read (sockfd, buffer, 1024);
          buffer[nbytes] = '\0';
          fputs (buffer, stdout);
        }
    }
  else
    {
      while (1)
        {
          fgets (hello, sizeof (hello), stdin);
          if (write (sockfd, hello, strlen (hello)) < 0)
            {
              perror ("write() error\n");
              exit (1);
            }

        }
    }
  /* 結(jié)束通訊     */
  close (sockfd);
  exit (0);
}
作者: 小兔吉    時間: 2012-07-30 01:31
server端接收數(shù)據(jù)之后,你關(guān)閉了socket,建立的連接就終止了,然后while循環(huán)繼續(xù),阻塞在accept處。client端write函數(shù)應(yīng)該報錯了吧。
作者: 流氓無產(chǎn)者    時間: 2012-07-30 08:52
server的child/father各自在干嗎?child close了,father還在等輸入
father應(yīng)該只是在等 ,child要干現(xiàn)在child/father的干活
作者: 嵌入式教父    時間: 2012-07-30 21:44
client端沒報錯,就是一直死在那,數(shù)據(jù)發(fā)不出去,收不到,不知道是客戶端,還是服務(wù)端的問題回復(fù) 2# 小兔吉


   
作者: 嵌入式教父    時間: 2012-07-30 21:47
不太明白,send,reciver都在子進(jìn)程內(nèi)完成嗎?回復(fù) 3# 流氓無產(chǎn)者


   
作者: xxwade    時間: 2012-07-30 23:30
accept函數(shù)從監(jiān)聽隊列中取出連接請求。server收到client信息后new_fd關(guān)閉,server與client斷開連接。同時,new_fd關(guān)閉給該describer解鎖,即可以修改new_fd指向的對象。而程序中并沒有再次指定,所以它還是指向client_addr。由于之前的連接斷開,server中子進(jìn)程發(fā)送數(shù)據(jù)的方式其實是udp。因而客戶端能夠收到。而此后客戶端再也沒有connect服務(wù)器,因而服務(wù)器的監(jiān)聽隊列中一直沒有數(shù)據(jù),即被阻塞在accpet處。
作者: 小兔吉    時間: 2012-07-31 00:53
你的serve端與client端通信的處理不對稱。

server端代碼中,accept是處于while循環(huán)中的。
server端accept取出一個就緒的client連接,創(chuàng)建子進(jìn)程讀數(shù)據(jù)然后close socket,父進(jìn)程則負(fù)責(zé)寫數(shù)據(jù)然后close socket,因此進(jìn)行一次讀寫數(shù)據(jù)之后,這個已連接的socket就無效了。進(jìn)入下一次循環(huán)重新accept。

client端代碼中,connect僅有一次,未處于循環(huán)中,也就是client這個進(jìn)程與server只能建立一次連接。
建立連接后,由于server端進(jìn)行一次讀寫之后關(guān)閉了已連接的socket,那么client端write函數(shù)實際上寫入一個已關(guān)閉的socket句柄中,雖然沒有報錯。至于read函數(shù),server端將socket關(guān)閉之后,應(yīng)該會返回0,至于下一次read的行為,我也不清楚。
因此client端父子進(jìn)程中的后續(xù)的read、write都與server端無關(guān)了。

不清楚你要寫成那個樣子。如果僅僅是一個client連接server的話,那server端也沒必要把accept放到while中,只需要像client端那樣將父子進(jìn)程中read、write函數(shù)放到循環(huán)中處理就行了。你要處理多個client連接的話,那就把read、write處理都放到子進(jìn)程中,父進(jìn)程只負(fù)責(zé)循環(huán)accpet。

回復(fù) 4# 嵌入式教父


   
作者: 嵌入式教父    時間: 2012-07-31 12:52
恩,這下明白了,非常感謝!講的很透徹,讓我對socket編程又有了更進(jìn)一步的理解回復(fù) 7# 小兔吉


   
作者: 嵌入式教父    時間: 2012-07-31 12:54
哦,明白了,這么個流程啊,謝謝,又學(xué)到不少 回復(fù) 6# xxwade


   
作者: lxk899    時間: 2012-08-01 09:39
回復(fù) 6# xxwade


   正解, 每次調(diào)用服務(wù)端accept后,客戶機都要調(diào)用connect去連接的。所以只要在服務(wù)端把accept移到while之前就應(yīng)該可以了吧。




歡迎光臨 Chinaunix (http://www.72891.cn/) Powered by Discuz! X3.2