Linux网络编程二、tcp连接API

时间:2021-07-07 00:06:02

  1、创建套接字:

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

      domain:指定协议族,通常选用AF_INET。

      type:指定socket类型,TCP通信下使用SOCK_STREAM。

      protocol:指定协议,通常为0。

      返回值:成功则返回新socket的文件描述符,失败返回-1。

      头文件:sys/socket.h     sys/types.h

  2、绑定套接字

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

      sockfd:要绑定的套接字。

      my_addr:本地地址,使用sockaddr_in结构体创建。

      addrlen:my_addr的长度。

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

  3、监听套接字

    int listen(int s, int backlog);

      s:要监听的套接字

      backlog:指定未完成连接队列的最大长度,如果一个连接请求到达时为完成连接队列已满,那么客户端将会接收到错误。

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

  4、接受连接

    int accept(int s, struct sockaddr *addr, socklen_t *addrlen);

      s:接收连接请求的套接字。

      addr:获取客户端信息。

      addrlen:addr的长度。

      返回值:成功返回一个非负整数表示的连接套接字,失败返回-1。

  5、读取数据

    ssize_t read(int fd, void *buf, size_t count);

      fd:文件描述符。

      buf:缓冲区,读取的数据放在缓冲区中。

      count:缓冲区大小。

      返回值:成功返回读取到的字节数,失败返回-1。

      注:read会阻塞。

    ssize_t recv(int sockfd, void *buf, size_t len, int flags);

      flags:一般设置为0。

      其余同上

  6、写数据

    ssize_t write(int fd, const void *buf, size_t count);

      同上。

    int send(int s, const void *msg, size_t len, int flags);

      同上。

  7、关闭套接字

    int close(int fd);

      fd:要关闭的套接字。

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

  8、其他

    将本地编码转为网络编码

    #include <arpa/inet.h>

    uint32_t htonl(uint32_t hostlong);

    uint16_t htons(uint16_t hostshort);

    uint32_t ntohl(uint32_t netlong);

    uint16_t ntohs(uint16_t netshort);

    将网络编码转为本地

    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

      af:协议族。

      src:原数据。

      dst:缓冲区。

      size:缓冲区大小。

      返回值:成功返回转换后的字符串,失败返回NULL。

//tcp_server.c #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <arpa/inet.h> #include <ctype.h> #include <unistd.h> #include <stdlib.h> int main() { const int lfd=socket(AF_INET,SOCK_STREAM,0); if(lfd==-1) { perror("socket error"); exit(1); } struct sockaddr_in server; memset(&server,0,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(8888); server.sin_addr.s_addr=htonl(INADDR_ANY); //设置端口复用 int flag=1; setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag)); int ret=bind(lfd,(struct sockaddr*)&server,sizeof(server)); if(-1==ret) { perror("bind error"); exit(1); } ret=listen(lfd,20); if(ret==-1) { perror("listen error"); exit(1); } struct sockaddr_in client; socklen_t len=sizeof(client); int cfd =accept(lfd,(struct sockaddr*)&client,&len); if(cfd==-1) { perror("accept error"); exit(1); } printf("accept successful !!!\n"); char ipbuf[64]={0}; printf("client IP: %s,port: %d\n",inet_ntop(AF_INET,&client.sin_addr.s_addr,ipbuf,sizeof(ipbuf)),ntohs(client.sin_port)); while(1) { char buf[1024]={0}; int len=read(cfd,buf,sizeof(buf)); if(len==-1) { perror("read error"); exit(1); } else if(len==0) { close(cfd); break; } else { printf("recv buf: %s\n",buf); for(int i=0;i<len;++i) { buf[i]=toupper(buf[i]); } printf("send buf: %s\n",buf); write(cfd,buf,len); } } close(cfd); close(lfd); return 0; }

二、客户端

  1、创建套接字

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

  2、连接客户端

    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

      sockfd:客户端创建的套接字。

      addr:配置的要连接的服务器。

      addrlen:addr的长度。

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

  3、通信

    同服务端,略。

tcp_client.c: