欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

socket实现客户端与服务端之间的Tcp通信

程序员文章站 2022-06-06 16:08:31
...

TCP通信流程分析:

server:
	1. socket(int socket_family, int socket_type, int protocol)	创建socket,返回用于监听的套接字

	2. bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)	绑定服务器地址结构(IP+port)

	3. listen(fd, 128)	设置监听上限

	4. accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)阻塞监听客户端连接,sockfd为socket函数返回值,返回新的已经成功与客户端连接的的文件描述符

	5. ssize_t read(int fd,void *buf, size_t count)	读socket获取客户端数据

	6. 小写转大写	toupper()

	7. ssize_t write(int fd, const void *buf, size_t count)  //向缓冲区写入数据

	8. close();

client:

	1. socket()	创建socket

	2. int connect(int socketfd, const struct sockaddr *addr, socklen_t addrlen);	与服务器建立连接

	3. write()	写数据到 socket

	4. read()	读转换后的数据。

	5. 显示读取结果

	6. close()

相关函数及参数说明

htonl() 本地字节序转网络字节序(IP)
htons() 本地字节序转网络字节序(port)
ntohl() 网络字节序转本地字节序(IP)
ntohs() 网络字节序转本地字节序(port)

//点分十进制IP地址转换为网络字节序
 int inet_pton(int af, const void *src, char *dst, socklen_t size);
//网络字节序转点分十进制IP地址
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

sockaddr_in地址结构:
          struct sockaddr_in {
          sa_family_t sin_family; /* 地址族: AF_INET */
          u_int16_t sin_port; /* 按网络字节次序的端口 */
          struct in_addr sin_addr; /* internet地址 */
          };

          /* Internet地址. */
          struct in_addr {
          u_int32_t s_addr; /* 按网络字节次序的地址 */
          };
          
sockaddr_in初始化:
struct sockaddr_in addr;
addr.sin_family = AF_INET/AF_INET6;  //IPv4或IPv6
addr.sin_port = htons(9527);  //将本地字节序转为short类型的网络字节序
//方法一,实际一般不这么用
    int dst;
    inet_pton(AF_INET, "192.127.22.45",(void *)dst);
addr.sin_addr.s_addr = dst;
//方法二
addr.sin_addr.s_addr = htonl(INADDR_ANY);//取出系统中有效的任意IP地址。
在实际作为accept、connect函数的参数使用时还要将sockaddr_in强转为sockaddr类型

服务端

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

#define SERV_PORT 9528

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc, char *argv[])
{
    int lfd, cfd;//监听文件描述符,client文件描述符
    char buf[BUFSIZ], client_IP[1024];
    int i;

    struct sockaddr_in serv_addr, clit_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    lfd = socket(AF_INET, SOCK_STREAM, 0);
    if(lfd == -1) sys_err("socket error");

    int ret = bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if(ret == -1) sys_err("bind error");

    ret = listen(lfd, 128);
    if(ret == -1) sys_err("listen error");

    socklen_t clit_addr_len = sizeof(clit_addr);
    cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len);
    if(cfd == -1) sys_err("accept error");

    printf("client IP:%s, port:%d\n", 
            inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr, client_IP, sizeof(client_IP)),
            ntohs(clit_addr.sin_port));
    while(1)
    {
        ssize_t readsize = read(cfd, buf, sizeof(buf));
        for(i=0; i<readsize; i++)
            buf[i] = toupper(buf[i]);
        write(cfd, buf, readsize);
    }
    close(lfd);
    close(cfd);
    return 0;
}

客户端

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

#define SERV_PORT 9528

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

int main(int argc, char *argv[])
{
    int cfd;
    int counter = 10;
    char buf[BUFSIZ];

    struct sockaddr_in serv_addr;  //服务器地址结构
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT);

    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
    //serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd == -1) sys_err("socket error");

    int ret = connect(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if(ret != 0) sys_err("connect error");

    while(--counter)
    {
        write(cfd, "hello\n", sizeof("hello\n"));
        ret = read(cfd, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, ret);
        sleep(1);
    }

    close(cfd);

    return 0;
}