zoukankan      html  css  js  c++  java
  • 套接字编程基础

     

    套接字是通信断点的抽象,网络编程中,套接字对于大多数通信细节做了隐藏,使程序员操作起来比较简单。

    1、建立和销毁套接字描述符

    Linux环境中使用socket函数创建一个套接字,函数原型如下:

    int socket(int domain,int type,int protocol);

    头文件:  #include<sys/types.h>、#include<sys/socket.h> 

    参数说明:

    第一个参数domain是通信域,“AF_INET”表示IPv4,“AF_INET6”表示IPv6。

    第二个参数是套接口的类型,SOCK_STREAM表示是TCP协议,SOCK_DGRAM表示是UDP协议,SOCK_RAW表示是绕过协议,SOCK_SEQPACKET表示STCP协议。

    第三个参数通常设置为0。

    返回值:系统调用socket()只返回一个套接口描述符,如果出错,则返回-1。

    2、地址绑定

    只有绑定了地址的套接字才能用于网络通信,因此需要将套接字与一个地址绑定,Linux环境下使用bind()函数将一个套接字绑定到一个地址上,函数如下:

    int bind(int sockfd,struct sockaddr*my_addr,int addrlen);

    头文件:#include<sys/types.h>、#include<sys/socket.h>

    参数说明:

    第一个参数sockfd是由socket()调用返回的套接口文件描述符。

    第二个参数my_addr是指向数据结构sockaddr的指针。数据结构sockaddr中包括了关于你的地址、端口和IP地址的信息。

    第三个参数addrlen可以设置成sizeof(structsockaddr)。

    返回值:如果绑定成功函数返回0,失败返回-1。

    3、建立一个连接

    套接字与地址绑定之后,就可以建立一个连接,在Linux环境下使用connect函数主动建立一个连接,函数原型如下:

    int connect(int sockfd,struct sockaddr* serv_addr,int addrlen);

    头文件:#include<sys/types.h>、#include<sys/socket.h>

    参数说明:

    第一个参数还是套接口文件描述符,它是由系统调用socket()返回的。

    第二个参数是serv_addr是指向数据结构sockaddr的指针,其中包括目的端口和IP地址。

    第三个参数可以使用sizeof(structsockaddr)而获得。

    返回值:如果建立连接成功函数返回0,失败返回-1。

    客户端主动建立连接,服务器端接受连接。服务器端接受连接分为两步,第一步,创立一个套接字监听连接请求,第二步,创立一个新的套接字接受并且处理请求。Linux环境中使用listen函数监听连接请求,函数如下:

    intl isten(int sockfd,int backlog);

    头文件:#include<sys/socket.h>

    参数说明:

    第一个参数是用来进行连接请求监听的套接字描述符。

    第二个参数表示最多可以排队等待连接的请求数量。

    返回值:成功返回0,失败返回-1。

    调用listen函数之后,该套接字就可以开始监听请求了,接受连接请求使用accept函数,函数如下:

    intaccept(intsockfd,void*addr,int*addrlen);

    头文件:#include<sys/socket.h>

    参数说明:

    第一个参数是正在监听端口的套接口文件描述符。

    第二个参数是一个地址结构,改地址往往是客户端的地址,一般设置为NULL。

    第三个参数表示取得的客户端地址的大小,这个值要小于用户提供的缓冲区大小。如果忽略改地址,设置为NULL.

    返回值:成功返回0,失败返回-1。

    应用实例:

    服务器端程序

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <ctype.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #define MAX_LINE 100
     
    /*处理函数,用于将大写字符转换成小写字符。参数为需要转换的字符串*/
    void my_fun(char *p)
    {
           if(p == NULL)
                  return ;
           for(; *p != ''; p++)
                  if(*p >= 'A' && *p <= 'Z')
                         *p = *p - 'A' + 'a';
    }
     
    int main(void)
    {
           struct sockaddr_in sin;
           struct sockaddr_in cin;
           int l_fd;
           int c_fd;
           socklen_t len;
           char buf[MAX_LINE];                         ///存储传送内容的缓存
           char addr_p[INET_ADDRSTRLEN];      ///存储客户端地址的缓冲区
           int port = 8000;                          ///端口号,使用8000
           int n;                                                 ///读写字节数
           bzero(&sin, sizeof(sin));        ///清空地址空间
           sin.sin_family = AF_INET;            ///使用IPv4通信域
           sin.sin_addr.s_addr = INADDR_ANY;///服务器可以接受任意地址
           sin.sin_port = htons(port);           ///端口号转换为网络字节序
           /*创立套接字,使用TCP协议*/
           l_fd = socket(AF_INET, SOCK_STREAM, 0);
           /*将地址和套接字绑定*/
           bind(l_fd, (struct sockaddr*)&sin, sizeof(sin));
           /*开始监听链接请求*/
           listen(l_fd, 10);
           printf("waiting ...
    ");
           /*服务器程序多半是死讯环
            * 接受链接请求,函数中返回后就可以开始通信了
            * */
           while(1)
           {
                  c_fd = accept(l_fd, (struct sockaddr*)&cin, &len);
                  n = read(c_fd, buf, MAX_LINE);
                  inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));
                  printf("client IP is %s, port is %d
    ", addr_p, ntohs(cin.sin_port));
                  printf("content is : %s
    ", buf);
                  my_fun(buf);
                  write(c_fd, buf, n);
                  close(c_fd);
           }
           return 0;
    }

    客户端程序:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <strings.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #define MAX_LINE 100
     
    int main(int argc, char *argv[])
    {
           struct sockaddr_in sin;
           char buf[MAX_LINE];
           int sfd;
           int port = 8000;
           char *str = "test sting";
           if(argc > 1)
           {
                  str = argv[1];
           }
           bzero(&sin, sizeof(sin));
           sin.sin_family = AF_INET;   ///使用IPv4地址族
          
           /*和本机通信,同一台主机担任服务器和客户端的角色*/
           inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr);
           sin.sin_port = htons(port);
           sfd = socket(AF_INET, SOCK_STREAM, 0);
           connect(sfd, (const struct sockaddr *)&sin, sizeof(sin));
           write(sfd, str, strlen(str) + 1);
           read(sfd, buf, MAX_LINE);
           printf("receive from serev : %s
    ", buf);
           close(sfd);
           return 0;
    }
  • 相关阅读:
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
  • 原文地址:https://www.cnblogs.com/Mr--Yang/p/6686910.html
Copyright © 2011-2022 走看看