汪自强

导航

TCP网络程序设计

 

 
 

 

 
11.7 创建套接字
11.7.1 函数名
socket
11.7.2 函数原形
  int socket(int domain, int type, int protocol);
11.7.3 函数功能
 
用于创建套接字
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
  #include <sys/socket.h>
11.7.5 返回值
 
成功:返回文件fd
失败:-1
11.7.6 参数说明
domain:通信域
  AF_INET,AF_INET6,AF_UNIX
type: 套接字类型
  SOCK_DGRAM,SOCK_RAW,SOCK_SEQPACKET
protocol :一般为0

 

 
11.7 绑定套接字
11.7.1 函数名
bind
11.7.2 函数原形
  int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
11.7.3 函数功能
 
用于绑定套接字
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
  #include <sys/socket.h>
11.7.5 返回值
 
成功:0
失败:-1
11.7.6 参数说明
sockfd:绑定套接字的文件描述符
addr: 套接字地址指针,下面是通用的地址类型
  struct sockaddr {
  sa_family_t sa_family;
  char sa_data[14];
  }
  常用的IPV4的地址类型如下:
  struct sockaddr_in {
  short int sin_family;
  unsigned short int sin_port;
  struct in_addr sin_addr;//一个整数表示IP地址
  unsigned char sin_zero[8];}
struct in_addr {
  unsigned long s_addr;
}
addrlen:地址长度
 
 

 

 
以上使用一个整数表示IP地址,但是人们一般是使用4个字符串来表示IP地址,使用下面两个函数就可以进行转换

 

 
  • 网络字节序
 
1. Little endian:将低序字节存储在起始地址
2. Big endian:将高序字节存储在起始地址
 

 

而网络上传输的模式都是大端模式,所以就有主机字节序-》网络字节序-》本机字节序

 

 
 

 

 
 

11.7 监听套接字

11.7.1 函数名
listen
11.7.2 函数原形
   int listen(int sockfd, int backlog);
11.7.3 函数功能
用于监听套接字
11.7.4 所属头文件
#include <sys/types.h>          /* See NOTES */
      #include <sys/socket.h>
11.7.5 返回值
成功:0
失败:-1
11.7.6 参数说明
sockfd:绑定套接字的文件描述符
backlog:该进程所要入队的最大长度
 
 

11.7 等待连接

11.7.1 函数名
accept
11.7.2 函数原形
  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
11.7.3 函数功能
 
用于等待客户机连接
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
  #include <sys/socket.h>
11.7.5 返回值
成功:返回新的一个文件描述符
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
addr:一个指向套接字地址的指针
addrlen:地址的长度
 
 

 

 
11.7 发送数据
11.7.1 函数名
accept
11.7.2 函数原形
  ssize_t send(int sockfd, const void *buf, size_t len, int flags);
11.7.3 函数功能
 
用于发送数据
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
  #include <sys/socket.h>
11.7.5 返回值
成功:返回发送的字节数
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
buf:待发送数据指针
len:数据长度
flags:标志,一般为0
 
 

 

 
 
11.7 接收数据
11.7.1 函数名
recv
11.7.2 函数原形
  ssize_t recv(int sockfd, void *buf, size_t len, int flags);
11.7.3 函数功能
 
用于接收数据
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
  #include <sys/socket.h>
11.7.5 返回值
成功:接收消息的字节数
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
buf:待发送数据指针
len:数据长度
flags:标志,一般为0
 
 

11.7 关闭结束连接

11.7.1 函数名
close
11.7.2 函数原形
  int close(int fd);
11.7.3 函数功能
 
用于关闭连接
11.7.4 所属头文件
#include <unistd.h>
11.7.5 返回值
 
成功:0
失败:-1
11.7.6 参数说明
fd:被关闭套接字的文件描述符
 
 
 
 
  • 客户机的函数
 

11.7 客户机连接服务器

11.7.1 函数名
connect
11.7.2 函数原形
  int connect(int sockfd, const struct sockaddr *addr,
  socklen_t addrlen);
11.7.3 函数功能
 
用于客户机连接服务器
11.7.4 所属头文件
#include <sys/types.h> /* See NOTES */
  #include <sys/socket.h>
11.7.5 返回值
 
成功:0
失败:-1
11.7.6 参数说明
sockfd:创建的套接字的文件描述符
addr:服务器的地址指针
addrlen:地址长度
 
 
 
 
  • 程序调试
调试过程中服务器程序遇到core dump问题,使用GDB调试发现是
printf("server get connection from %s\r\n",inet_ntoa(client_addr.sin_addr));//将客户机地址转化成字符串,打印客户机地址
这句话引起了Segmentation on on vprintf.c的错误,
在网络上查询发现是要包含以下头文件
#include <arpa/inet.h>//使用inet_ntoa网络地址转换成字符串函数需包含的头文件

 

 
服务器程序
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>//使用struct sockaddr_in需包含的头文件
#include <arpa/inet.h>//使用inet_ntoa网络地址转换成字符串函数需包含的头文件
#include <string.h>
#include <stdio.h>
 
#define portnum 3333//自定义网络端口
int main()
{       
    int sockfd,new_fd;//定义文件描述符,新的客户机文件描述符                 
    struct sockaddr_in server_addr;//主机地址属性                           
    struct sockaddr_in client_addr;//客户机地址                             
    char buffer[128];//接收数据缓存                                         
    int nbyte;                                                             
    int sin_size;                                                           
 
    //1.创建套接字                                                         
    if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)//如果创建错误,就返回 
    {   
        printf("create socket error\r\n");                                 
        exit(1);                                                           
    }   
    //2.1 设置要绑定的地址                                                 
    bzero(&server_addr,sizeof(struct sockaddr_in));//将地址结构体先清零     
    server_addr.sin_family = AF_INET;       //网络域                       
    server_addr.sin_port   = htons(portnum);//将两个字节的端口转换成网络字节序
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//将任意的IP地址赋予数据段
 
    //2.2绑定地址                                                                                                                           
    bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr));
    //第二个参数一般先使用sockaddr_in(便于定义结构体成员变量),然后在强制转化,能够更方便
 
    //3.监听端口                                                             
    listen(sockfd,5);//最大连接数是5                                         
 
    while(1)                                                                 
    {                                                                       
        //4.等待连接                                                         
        sin_size = sizeof(struct sockaddr);                                 
        new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size);//等待连接,注意第三个参数必须是指针
        printf("server get connection from %s\r\n",inet_ntoa(client_addr.sin_addr));//将客户机地址转化成字符串,打印客户机地址
 
        //5.接收数据                                                         
        nbyte = recv(new_fd,buffer,128,0);                                   
        buffer[nbyte] = '\0';                                               
        printf("server recv : %s\r\n",buffer);//打印接收的数据               
 
        //6.结束连接                                                         
        close(new_fd);                                                       
        //break;                                                             
    }                                                                       
 
    close(sockfd);                                                           
 
}                       
 

 

 
客户机程序
#include <sys/types.h> /* See NOTES */                                                                                                       
#include <sys/socket.h>
#include <netinet/in.h>i//定义了sockaddr_in结构
#include <string.h>
#include <stdio.h> 
 
#define portnum 3333//自定义网络端口
int main()         
{
    int sockfd,new_fd;//定义文件描述符,新的客户机文件描述符
    struct sockaddr_in server_addr;//主机地址属性
    char buffer[128];//接收数据缓存
    int nbyte;
 
    //1.创建套接字
    if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1)//如果创建错误,就返回
    {
        printf("create socket error\r\n");
        exit(1);
    }
 
    //2.1 设置要连接的服务器的地址
    bzero(&server_addr,sizeof(struct sockaddr_in));//将地址结构体先清零
    server_addr.sin_family = AF_INET;       //网络域
    server_addr.sin_port   = htons(portnum);//将两个字节的端口转换成网络字节序
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.141");//服务器的地址
 
    //2.2连接服务器
    if((connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))) == -1)
    {
        printf("connect error\r\n");
        exit(1);
    }
 
    //3.发送数据到服务器
    printf("Please input char sent to server\r\n");
    fgets(buffer,128,stdin);
    send(sockfd,buffer,strlen(buffer),0);
 
    //4.关闭连接
    close(sockfd);
 
    return 0;
 
}

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

posted on 2017-04-03 22:50  汪自强  阅读(405)  评论(0编辑  收藏  举报