Linux網路編程之聊天程式(TCP協議之fork進程)

來源:互聯網
上載者:User

實現了服務端和用戶端之間的相互聊天,不收順序限制,可以同時進行。

服務端: server.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MAXBUF 1024

int main(int argc, char *argv[])
{
    int pid;
    int sockfd, new_fd;
    socklen_t len;
    struct sockaddr_in my_addr, their_addr;
    unsigned int myport, lisnum;
    char buf[MAXBUF + 1];

    if (argv[2])
myport = atoi(argv[2]);    /* 將命令列字串轉換為整數,用於連接埠 */
    else
myport = 7575;     /* 設定預設連接埠 */


    if (argv[3])
lisnum = atoi(argv[3]);  /* 監聽隊列大小 */
else
lisnum = 5;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)   /* 建立socket對象 */
    {
perror("socket");
exit(EXIT_FAILURE);
    }
    
    bzero(&my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;               /* 地址協議 */
    my_addr.sin_port = htons(myport);           /* 地址連接埠 */  
    if (argv[1])
my_addr.sin_addr.s_addr = inet_addr(argv[1]);
    else
my_addr.sin_addr.s_addr = INADDR_ANY;     /* 否則預設本機任意地址 */

    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))== -1)  /* 綁定地址資訊 */
    {
perror("bind");
exit(EXIT_FAILURE);
    }

    if (listen(sockfd,lisnum ) == -1)      /* 監聽網路 */
    {
perror("listen");
exit(EXIT_FAILURE);
    }
    printf("wait for connect\n");
    len = sizeof(struct sockaddr);
    if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1) 
/* 阻塞等待串連,串連成功返回新的socket描述符,their_addr儲存用戶端的sockaddr 地址資訊
{
        perror("accept");
        exit(EXIT_FAILURE);
    } 
    else
 printf("server: got connection from %s, port %d, socket %d\n",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port), new_fd);
   
if(-1==(pid=fork()))      /* 建立新進程 */
{
perror("fork");exit(EXIT_FAILURE);
}
else if( pid == 0)           /* 子進程用於發送訊息 */
{
while (1) 
{
bzero(buf, MAXBUF + 1);
printf("input the message to send:");
fgets(buf, MAXBUF, stdin);
if (!strncasecmp(buf, "quit", 4)) 
{
printf("i will close the connect!\n");
break;
}
len = send(new_fd, buf, strlen(buf) - 1, 0);
  if (len < 0)
{
printf("message'%s' send failure!errno code is %d,errno message is '%s'\n",
buf, errno, strerror(errno));
break;
}
}
}
else                                          /* 父進程用於接收訊息 */
{
while(1)
{
bzero(buf, MAXBUF + 1);
len = recv(new_fd, buf, MAXBUF, 0);
if (len > 0)
printf("message recv successful :'%s',%dByte recv\n",buf, len);
else if (len < 0)
{
printf("recv failure!errno code is %d,errno message is '%s'\n",
errno, strerror(errno));
break;
}
else
{
printf("the other one close quit\n");
break;
}
}
}
close(new_fd);
close(sockfd);
    return 0;
}


用戶端程式: client.c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define MAXBUF 1024

int main(int argc, char **argv)
{
    int sockfd, len;
    struct sockaddr_in dest;
    char buffer[MAXBUF + 1];
    if (argc != 3) 
    {
printf(" error format,it must be:\n\t\t%s IP port\n",argv[0]);
exit(EXIT_FAILURE);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {        /* 建立socket對象 */
perror("Socket");
exit(errno);
    }
    printf("socket created\n");

    bzero(&dest, sizeof(dest));                             /* 清零操作 */
    dest.sin_family = AF_INET;                              /* 地址協議 */
    dest.sin_port = htons(atoi(argv[2]));  /* 地址連接埠 */  
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0)   /* 對方IP地址 */
    {
perror(argv[1]); exit(errno);
    }
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest))==-1)        /* 發起串連 */
    {
perror("Connect ");
exit(errno);
    }
    printf("server connected\n");

pid_t pid;
if(-1==(pid=fork()))                                     /* 建立新進程 */
{
perror("fork");exit(EXIT_FAILURE);
}
else if (pid==0)                              /* 子進程用於接收訊息,不懂進程的自己去百度一下吧 */
{
while (1) 
{
bzero(buffer, MAXBUF + 1);
len = recv(sockfd, buffer, MAXBUF, 0);
if (len > 0)
printf("recv successful:'%s',%d byte recv\n",buffer, len);
else if(len < 0)
{
perror("recv");
break;
}
else
{
printf("the other one close ,quit\n");
break;
}
}
}
else                                   /* 父進程用於發送訊息 */
{
while (1) 
{
bzero(buffer, MAXBUF + 1);
printf("pls send message to send:");
fgets(buffer, MAXBUF, stdin);
if (!strncasecmp(buffer, "quit", 4)) 
{
printf(" i will quit!\n");
break;
}
len = send(sockfd, buffer, strlen(buffer) - 1, 0);
if (len < 0) 
{
perror("send");
break;
}
}
}
    close(sockfd);
    return 0;
}

測試方法如下:
gcc server.c -o server
gcc client.c -o client
./server 172.16.148.114  8888       /* 一個終端下,172.16.148.114是我虛擬機器的IP地址*/
./client 172.16.148.114  8888      /*另外 一個終端下 */


補充一個知識點:
int shutdown(int sockfd,int how);
shutdown可直接關閉描述符,不考慮描述符的參考數,可選擇中止一個方向的串連
how的方式有三種分別是
SHUT_RD(0):關閉sockfd上的讀功能,此選項將不允許sockfd進行讀操作。
SHUT_WR(1):關閉sockfd的寫功能,此選項將不允許sockfd進行寫操作。
SHUT_RDWR(2):關閉sockfd的讀寫功能。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.