以下内容纯属个人理解,请大神勿喷,还请大神在评论区指教,谢谢
server.cpp
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> int main(){ //创建套接字 int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //将套接字和IP、端口绑定 struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充 serv_addr.sin_family = AF_INET; //使用IPv4地址 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址 serv_addr.sin_port = htons(1234); //端口 bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); //进入监听状态,等待用户发起请求 listen(serv_sock, 20); //接收客户端请求 struct sockaddr_in clnt_addr; socklen_t clnt_addr_size = sizeof(clnt_addr); int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size); //向客户端发送数据 char str[] = "http://c.biancheng.net/socket/"; write(clnt_sock, str, sizeof(str)); //关闭套接字 close(clnt_sock); close(serv_sock); return 0; }
client.cpp
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> int main(){ //创建套接字 int sock = socket(AF_INET, SOCK_STREAM, 0); //向服务器(特定的IP和端口)发起请求 struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充 serv_addr.sin_family = AF_INET; //使用IPv4地址 serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址 serv_addr.sin_port = htons(1234); //端口 connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); //读取服务器传回的数据 char buffer[40]; read(sock, buffer, sizeof(buffer)-1); printf("Message form server: %s\n", buffer); //关闭套接字 close(sock); return 0; }
服务端bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));将serv_sock套接字和ip、端口绑定在一起,服务器listen()监听,客户端请求连接connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)),sock是指服务器数据发送到sock接收缓冲区里面(个人理解),serv_addr保存了服务器的ip和端口,为了到达对方那边请求连接,sizeof(serv_addr),不知道为什么需要这个参数。到达了服务器那边请求连接,服务器被唤醒,accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);,serv_sock,为了判断是否接受连接,这个里面绑定有ip和端口嘛,clnt_addr接受客户端serv_addr保存的IP地址和端口号,然后和serv_sock的ip和端口比较一下是不是连我的,是就看情况可以接受呗,不是那就不接受呗(个人理解),clnt_addr_size大小(不知道为什么需要这个参数),accept() 返回一个新的套接字来和客户端通信。连接完成(纯属个人理解,勿喷,希望能在评论区指教)
服务端新的套接字clnt_sock往clnt_sock写数据, write(clnt_sock, str, sizeof(str));read(sock, buffer, sizeof(buffer)-1);客户端读数据,具体流程在下方:
每一个TCP套接字有一个发送缓冲区,当某个进程调用write时,内核从该应用进程的缓冲区中复制所有数据到所写套接字的发送缓冲区。如果该套接字的发送缓冲区容不下该应用进程的所有数据,该应用进程将被投入睡眠,这里假设该套接字是阻塞的,它是通常的默认设置,内核将不从write系统调用返回,直到应用进程缓冲区中的所有数据都复制到套接字发送缓冲区。因此,从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用进程已接收到数据,对端TCP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端TCP至此才能从套接字发送缓冲区中丢弃已确认的数据。TCP必须为已发送的数据保留一个副本,直到它被对端确认为止。(涉及到计算机网络)
来源:https://blog.csdn.net/huang1600301017/article/details/99675531