一、socket地址api。socket最开始的含义是一个IP地址和端口对。他唯一地表示了使用TCP通信的一端。(主要讨论ipv4)

1、ipv4socket地址:

struct sockaddr_in{    sa_family_t sin_family;  /*地址族:AF_INET*/    u_int16 sin_port;        /*端口号,要用网络字节序表示*/    struct in_addr sin_addr; /*ipv4地址结构*/};struct in_addr{    u_int32_t s_addr;        /*ipv4地址,要用网络字节表示*/};

2、ip地址转换函数

/*字符串转in_addr*/#include
int inet_aton(const char *strptr,struct in_addr *addrptr);in_addr_t inet_addr(const char *strptr);int inet_pton(int family,const char *strptr,void *addrptr);/*in_addr转字符串*/char *inet_ntoa(struct in_addr inaddr);const char *inet_ntop(int family,const void *addrptr,char *strptr,size_t len);

其中inet_pton和inet_ntop不仅可以转换ipv4地址,而且可以转换ipv6的地址。

二、socket基础API。创建socket、命名socket、监听、socket、接收连接、发起连接、读写数据、获取地址信息。

#include
#include
/*创建socket*/int socket(int domain,int type,int protocol);/*domain表示那个协议,对于TCP/IP协议而言是PF_INET/PT_INET6;type服务类型,TCP使用SOCK_STREAML(流服务)、UDP使用SOCK_DGRAM(数据报);protocol一般情况都是0调用成功返回一个socket文件描述符,失败返回-1并设置errno*//*绑定或命名socket*/int bind(int sockfd,const struct sockaddr* my_addr,socklen_t addrlen);/*将my_addr所指的socket地址分配给未命名的sockfd文件描述符,addrlen参数是socket地址长度调用成功返回0,失败返回-1并设置errno。*//*监听socket*/int listen(int sockfd,int backlog);/*sockfd参数指定被监听的socket;backlog提示内核监听队列的最大长度,典型值是5。调用成功返回0,失败返回-1并设置errno。*//*接受连接*/int accept(int sockfd,struct sockaddr *addr,socklen_t* addrlen);/*sockfd参数是执行过listen系统调用的监听socket。addr参数用来获取接收连接的远端socket地址,该socket地址长度由addrlen参数指出。调用成功返回一个新的连接socket,该socket唯一地标识了被接收的这个连接,服务器可以通过读写该socket来与被接受连接对应的客户端通信。失败时返回-1并设置errno*//*向服务器发送连接*/int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);/*sockfd 参数有socket系统调用返回一个socket。serv_addr参数是服务器监听的socket地址,addlen参数指定这个地址的长度。调用成功返回0。一旦成功建立连接,sockfd就唯一地标识了这个连接,客户端就可以通过读写sockfd来与服务器通信。失败返回-1并设置errno*//*从socket上读取数据,向socket上写数据*/ssize_t recv(int sockfd,void *buf,size_t len,int flags);ssize_t send(int sockfd,const void *buf,size_t len,int flags);/*recv读取sockfd上的数据,buf和len参数分别指定缓冲区的位置和大小,flags参数通常是0send往sockfd上写入数据,buf和len参数分别指定写缓冲区的位置和大小。*//*关闭socket*/#include
int close(int fd);

三、使用TCP协议的socket编程的流程如下图

根据上面流程编写client.c

#include
  #include
  #include
  #include
  #include
  #include
  #include
    #define MAXLINE 4096    int main(int argc, char** argv)  {      int    sockfd, n,rec_len;      char    recvline[4096], sendline[4096];      char    buf[MAXLINE];      struct sockaddr_in    servaddr;          if( argc != 2){      printf("usage: ./client 
\n");      exit(0);      }        /*创建socket*/    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){      printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);      exit(0);      }       memset(&servaddr, 0, sizeof(servaddr));      servaddr.sin_family = AF_INET;      servaddr.sin_port = htons(8000);   /*转换socket地址*/    if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){      printf("inet_pton error for %s\n",argv[1]);      exit(0);      }      /*向服务器发起连接*/    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){      printf("connect error: %s(errno: %d)\n",strerror(errno),errno);      exit(0);      }       printf("send msg to server: \n");      fgets(sendline, 4096, stdin);   /*往socket上写数据*/    if( send(sockfd, sendline, strlen(sendline), 0) < 0)      {      printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);      exit(0);      }   /*从socket上读数据*/    if((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1) {         perror("recv error");         exit(1);      }      buf[rec_len]  = '\0';      printf("Received : %s ",buf);   /*关闭socket*/    close(sockfd);      exit(0);  }

server.c

#include
  #include
  #include
  #include
  #include
  #include
  #include
  #define DEFAULT_PORT 8000  #define MAXLINE 4096  int main(int argc, char** argv)  {      int    socket_fd, connect_fd;      struct sockaddr_in     servaddr;      char    buff[4096];      int     n;      /*创建Socket */    if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){      printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);      exit(0);      }      /*初始化*/      memset(&servaddr, 0, sizeof(servaddr));      servaddr.sin_family = AF_INET;      servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//我认为是任意地址      servaddr.sin_port = htons(DEFAULT_PORT);//设置的端口为DEFAULT_PORT        /*将本地地址绑定到所创建的套接字上*/    if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){      printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);      exit(0);      }      /*开始监听是否有客户端连接*/      if( listen(socket_fd, 10) == -1){      printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);      exit(0);      }      printf("======waiting for client's request======\n");      while(1){          /*阻塞直到有客户端连接,接收连接*/        if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1){          printf("accept socket error: %s(errno: %d)",strerror(errno),errno);          continue;      }      /*接受客户端传过来的数据*/    n = recv(connect_fd, buff, MAXLINE, 0);      /*向客户端发送回应数据*/ if(send(connect_fd, "Hello,you are connected!\n", 26,0) == -1)          perror("send error");      buff[n] = '\0';      printf("recv msg from client: %s\n", buff);      close(connect_fd);      }      close(socket_fd);  }

运行结果:

1、运行server程序

2、运行client程序

3、server接收成功