<>socket-通信-tcp协议

来源:互联网 发布:一小时学编程 编辑:程序博客网 时间:2024/04/27 15:35
 

《Makefile》

# Makefile
#

#CROSS_COMPILE = arm-linux-gnu-

CC = $(CROSS_COMPILE)gcc

ifdef CROSS_COMPILE
TARGET = /opt/filesystem
endif

DEBUG = -g -O0 -Wall

CFLAGS += $(DEBUG)

PROGS = ${patsubst %.c, %, ${wildcard *.c}}

all : $(PROGS)

install: $(PROGS)
ifdef CROSS_COMPILE
 mkdir $(TARGET)/root/long_term/networks -p
 cp $(PROGS) $(TARGET)/root/long_term/networks -f
endif
% : %.c
 $(CC)  $(CFLAGS)  $< -o $@

.PHONY: uninstall clean dist

uninstall :
ifdef CROSS_COMPILE
 cd $(TARGET)/root/long_term/networks && rm -f $(PROGS)
endif

clean : uninstall
 - rm -f $(PROGS) core *.gz *~

dist: clean
 tar czf ../farsight_simple_select_demo1.41.tar.gz *.c ../myselect
 ***************************************************************************

《server》服务端,等待显示信息


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

#include "list.h"

struct cli_list
{
 struct list_head list;
 int clifd;
};

#define           DEF_SERV_PORT          5432
#define           DEF_SERV_IP          "192.168.1.101"

struct cli_list *head = NULL;

void usage (char *s)
{
 printf ("%s [ipaddr] [port]\n", s);
 printf ("[ipaddr] --options, your server IP addr,default is %s\n", DEF_SERV_IP);
 printf ("[port]   --options, your server listening port, default is %d\n\n", DEF_SERV_PORT);
//        exit (1);
}

static inline void broadcast_msg (struct cli_list *head, int sockfd, const void *buf, size_t len, int flags)
{
 int ret = -1;
 struct list_head *p, *n;
 struct cli_list *pnode;

 list_for_each_safe (p, n, &head->list) {
  pnode = list_entry (p, struct cli_list, list);
  if (pnode->clifd != -1 && pnode->clifd != sockfd) {
   do {
    ret = send (pnode->clifd, buf, len, flags);
   } while (ret < 0 && EINTR == errno);
   if (ret < 0) {
    printf ("broadcast failed\n");
   }
  } else {
   continue;
  }
 }

 return;
}

int main (int argc, char *argv[])
{
 char buf[BUFSIZ];

 int fd, newfd, len;
 socklen_t clen = -1;

 struct sockaddr_in sin;
 struct sockaddr_in cin;
 struct cli_list *mylist;

 char ip_dot_addr[17];
 fd_set rset;

 int b_reuse = 1;

 head = (struct cli_list *) malloc (sizeof (struct cli_list));
 if (!head) {
  printf ("malloc failed\n");
  exit (1);
 }
 head->clifd = -1;
 INIT_LIST_HEAD (&head->list);
 mylist = head;

 fd = socket (AF_INET, SOCK_STREAM, 0);
 if (fd < 0) {
  fprintf (stderr, "ERROR: Can not create socket!\n");
  exit (1);
 }

 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof (int));

 usage (argv[0]);   //give a guide.

 bzero ((char *) &sin, sizeof (sin));
 sin.sin_family = AF_INET;

 switch (argc) {
 case 1:
  sin.sin_addr.s_addr = INADDR_ANY;
  sin.sin_port = htons (DEF_SERV_PORT);
  break;
 case 3:
  sin.sin_addr.s_addr = inet_addr (argv[1]);
  sin.sin_port = htons (atoi (argv[2]));
  break;
 case 2:
  if (strchr (argv[1], '.') != NULL) { //argv[1] is server ip address
   sin.sin_addr.s_addr = inet_addr (argv[1]);
   sin.sin_port = htons (DEF_SERV_PORT);

  } else {    //argv[1] is server port
   sin.sin_port = htons (atoi (argv[1]));
   sin.sin_addr.s_addr = INADDR_ANY;
  }

  break;
 default:
  usage (argv[0]);
  exit (1);
  break;
 }

 if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
  fprintf (stderr, "bind error!\n");
  exit (1);
 }
 listen (fd, 10);

 strcpy (ip_dot_addr, "any IP");
 if (sin.sin_addr.s_addr != INADDR_ANY) {
  if (inet_ntop (AF_INET, (void *) &sin.sin_addr, ip_dot_addr, sizeof (ip_dot_addr)) == NULL) {
   fprintf (stderr, "inet_ntop error!\n");
   exit (1);
  }
  ip_dot_addr[16] = '\0';
 }
 printf ("Server bind at %s:%d\n", ip_dot_addr, ntohs (sin.sin_port));

 while (1) {

  struct cli_list *tmp;
  struct list_head *pos, *q;
  int maxfd = -1;

  /*1. 把fd,所有的已经建立好连接的socket描述符加入到rset */
  FD_ZERO (&rset);
  FD_SET (fd, &rset);
  maxfd = fd;

  list_for_each_safe (pos, q, &mylist->list) {
   tmp = list_entry (pos, struct cli_list, list);
   FD_SET (tmp->clifd, &rset);

   if (tmp->clifd > maxfd)
    maxfd = tmp->clifd;
  }

  /*2. 调用select() */
  select (maxfd + 1, &rset, NULL, NULL, NULL);

  /*3.查看那个文件描述符有数据 */
  if (FD_ISSET (fd, &rset) > 0) {
   /* 有新的客户端连接请求 */
   do {
    clen = sizeof (cin);
    newfd = accept (fd, (struct sockaddr *) &cin, &clen);
   } while (newfd < 0 && errno == EINTR);
   if (newfd < 0) {
    fprintf (stderr, "Err: Can't accept socket!\n");
    exit (1);
   }

   if (inet_ntop (AF_INET, (void *) &cin.sin_addr.s_addr, ip_dot_addr, sizeof (ip_dot_addr)) == NULL) {
    fprintf (stderr, "inet_ntop error!\n");
    exit (1);
   }
   ip_dot_addr[16] = '\0';

   printf ("Client %s:%d connected!\n", ip_dot_addr, ntohs (cin.sin_port));

   tmp = (struct cli_list *) malloc (sizeof (struct cli_list));
   if (tmp == NULL) {
    fprintf (stderr, "malloc error\n");
    exit (1);
   }
   tmp->clifd = newfd;
   list_add (&(tmp->list), &(mylist->list));
  }

  list_for_each_safe (pos, q, &mylist->list) {
   tmp = list_entry (pos, struct cli_list, list);

   if (FD_ISSET (tmp->clifd, &rset)) { /* 已建立的连接有数据可读 */
    int need_free_flags = 0;
    bzero (buf, BUFSIZ);
    do {
     len = read (tmp->clifd, buf, BUFSIZ);
    } while (len < 0 && EINTR == errno);

                buf[BUFSIZ -1] = '0';

    if (strncmp (buf, "quit", 4) == 0) {
     bzero(buf,BUFSIZ);
     sprintf(buf,"%s%d exited.\n", "fd=",tmp->clifd);
     need_free_flags = 1;
    }

                               /* output the string */
                               fprintf (stderr, "%s", buf);
 
    /* broadcasting */
    broadcast_msg (head, tmp->clifd, buf, strlen (buf), 0);
    if (need_free_flags) {
                                 close (tmp->clifd);
                                        list_del ((struct list_head *) tmp);
     free(tmp);
     tmp = NULL;
    }
   }
  }
 }
 close (fd);
 return 0;
}

执行:

lsb@ubuntu:~/gx/wangluo$ ./select_tcp_server 192.168.1.101
./select_tcp_server [ipaddr] [port]
[ipaddr] --options, your server IP addr,default is 192.168.1.101
[port]   --options, your server listening port, default is 5432

Server bind at 192.168.1.101:5432

等客户端起来后:

Client 192.168.1.101:52166 connected!

表示连接成功:

信息:(客户端发过来的信息)

kai shi lian jie

OK

*************************************************************

《client》客户端---即发信息端


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


#define           DEF_SERV_PORT          5432
#define    DEF_SERV_IP          "192.168.1.101"

void usage (char *s)
{
 printf ("%s [ipaddr] [port]\n", s);
 printf ("[ipaddr] --options, your server IP addr,default is %s\n", DEF_SERV_IP);
 printf ("[port]   --options, your server listening port, default is %d\n", DEF_SERV_PORT);
 exit (1);
}


int main (int argc, char *argv[])
{
 char buf[BUFSIZ], *p;

 struct sockaddr_in sin;

 int fd, len;

 fd_set rset;

 fd = socket (AF_INET, SOCK_STREAM, 0);
 if (fd < 0) {
  fprintf (stderr, "ERROR: Can not create socket!\n");
  exit (1);
 }

 bzero ((char *) &sin, sizeof (sin));
 sin.sin_family = AF_INET;

 switch (argc) {
 case 1:
  sin.sin_addr.s_addr = inet_addr (DEF_SERV_IP);
  sin.sin_port = htons (DEF_SERV_PORT);
  break;
 case 3:
  sin.sin_addr.s_addr = inet_addr (argv[1]);
  sin.sin_port = htons (atoi (argv[2]));
  break;
 case 2:
  if (strchr (argv[1], '.') != NULL) { //argv[1] is server ip address
   sin.sin_addr.s_addr = inet_addr (argv[1]);
   sin.sin_port = htons (DEF_SERV_PORT);

  } else {    //argv[1] is server port
   sin.sin_port = htons (atoi (argv[1]));
   sin.sin_addr.s_addr = inet_addr (DEF_SERV_IP);
  }

  break;
 default:
  usage (argv[0]);
  break;
 }

 if (connect (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
  fprintf (stderr, "connect error!\n");
  exit (1);
 }

 while (1) {
  int maxfd = -1;
  struct timeval delay = { 5, 0 };
  FD_ZERO (&rset);
  FD_SET (0, &rset);
  FD_SET (fd, &rset);

  maxfd = fd;
  /*2. 调用select() */
  select (maxfd + 1, &rset, NULL, NULL, &delay);

  /*3.查看那个文件描述符有数据 */
  if (FD_ISSET (fd, &rset) > 0) { /* 套接字有数据 */
   bzero (buf, BUFSIZ);
   do {
    len = read (fd, buf, BUFSIZ);
   } while (len < 0 && EINTR == errno);

   if (len > 0) {
    p = buf;
    while (len-- > 0)
     fprintf (stderr, "%c", *p++);
   }

  }
  if (FD_ISSET (0, &rset) > 0) { /* 标准输入终端有数据 */
   bzero (buf, BUFSIZ);
   do {
    len = read (0, buf, BUFSIZ);
   } while (len < 0 && EINTR == errno);

   if (len > 0) {
    send (fd, buf, len, 0);
   }
   
                        if (strncmp (buf, "quit", 4) == 0) {
                               sleep(1);
                         break;
   }

  }

 }
 close (fd);
 return 0;
}

执行:


lsb@ubuntu:~/gx/wangluo$ ./select_tcp_client 192.168.1.101
kai shi lian jie
OK
********************************************************************************

若先执行客户端的话,就会

connect error!
所以,一上来就连接客户端