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

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2122 | 回復: 9
打印 上一主題 下一主題

[C] 一個基于tcp的socket代碼,友們幫忙指點一下問題 [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2012-07-29 21:19 |只看該作者 |倒序瀏覽
下面代碼是局域網(wǎng)server同client相互發(fā)送數(shù)據(jù)代碼,代碼問題是為什么只能互相發(fā)送一次數(shù)據(jù),再發(fā)送,對方就收不到了,求教!
代碼如下:
/******* 服務器程序  (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);
    }

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

  /* 服務器端填充 sockaddr結構  */
  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)
    {

      /* 服務器阻塞,直到客戶程序建立連接  */
      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)結束     */
          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);
    }

  /* 客戶程序填充服務端的資料       */
  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);
            }

        }
    }
  /* 結束通訊     */
  close (sockfd);
  exit (0);
}

論壇徽章:
0
2 [報告]
發(fā)表于 2012-07-30 01:31 來自手機 |只看該作者
server端接收數(shù)據(jù)之后,你關閉了socket,建立的連接就終止了,然后while循環(huán)繼續(xù),阻塞在accept處。client端write函數(shù)應該報錯了吧。

論壇徽章:
208
巨蟹座
日期:2013-09-02 09:16:36卯兔
日期:2013-09-02 20:53:59酉雞
日期:2013-09-05 21:21:45戌狗
日期:2013-10-15 20:51:17寅虎
日期:2013-10-18 21:13:16白羊座
日期:2013-10-23 21:15:19午馬
日期:2013-10-25 21:22:48技術圖書徽章
日期:2013-11-01 09:11:32雙魚座
日期:2013-11-01 20:29:44丑牛
日期:2013-11-01 20:40:00卯兔
日期:2013-11-11 09:21:32酉雞
日期:2013-12-04 19:56:39
3 [報告]
發(fā)表于 2012-07-30 08:52 |只看該作者
server的child/father各自在干嗎?child close了,father還在等輸入
father應該只是在等 ,child要干現(xiàn)在child/father的干活

論壇徽章:
0
4 [報告]
發(fā)表于 2012-07-30 21:44 |只看該作者
client端沒報錯,就是一直死在那,數(shù)據(jù)發(fā)不出去,收不到,不知道是客戶端,還是服務端的問題回復 2# 小兔吉


   

論壇徽章:
0
5 [報告]
發(fā)表于 2012-07-30 21:47 |只看該作者
不太明白,send,reciver都在子進程內(nèi)完成嗎?回復 3# 流氓無產(chǎn)者


   

論壇徽章:
0
6 [報告]
發(fā)表于 2012-07-30 23:30 |只看該作者
accept函數(shù)從監(jiān)聽隊列中取出連接請求。server收到client信息后new_fd關閉,server與client斷開連接。同時,new_fd關閉給該describer解鎖,即可以修改new_fd指向的對象。而程序中并沒有再次指定,所以它還是指向client_addr。由于之前的連接斷開,server中子進程發(fā)送數(shù)據(jù)的方式其實是udp。因而客戶端能夠收到。而此后客戶端再也沒有connect服務器,因而服務器的監(jiān)聽隊列中一直沒有數(shù)據(jù),即被阻塞在accpet處。

論壇徽章:
0
7 [報告]
發(fā)表于 2012-07-31 00:53 |只看該作者
你的serve端與client端通信的處理不對稱。

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

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

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

回復 4# 嵌入式教父


   

論壇徽章:
0
8 [報告]
發(fā)表于 2012-07-31 12:52 |只看該作者
恩,這下明白了,非常感謝!講的很透徹,讓我對socket編程又有了更進一步的理解回復 7# 小兔吉


   

論壇徽章:
0
9 [報告]
發(fā)表于 2012-07-31 12:54 |只看該作者
哦,明白了,這么個流程啊,謝謝,又學到不少 回復 6# xxwade


   

論壇徽章:
0
10 [報告]
發(fā)表于 2012-08-01 09:39 |只看該作者
回復 6# xxwade


   正解, 每次調(diào)用服務端accept后,客戶機都要調(diào)用connect去連接的。所以只要在服務端把accept移到while之前就應該可以了吧。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP