服务器端工作流程:
调用 socket() 函数创建套接字 用 bind() 函数将创建的套接字与服务端IP地址和端口绑定
调用listen()函数监听socket() 函数创建的套接字,指定最大同时发起连接数
调用 accept()函数接受连接请求,阻塞等待。与客户端连接上,返回一个对应于此连接的新的套接字
调用 write()/read() 函数进行数据的读写,通过 accept() 返回的套接字和客户端进行通信 关闭socket(close)
客户端工作流程:
调用 socket() 函数创建套接字
调用 connect() 函数连接服务端
调用write()/read() 函数或者 send()/recv() 函数进行数据的读写
关闭socket(close)
疑问:
1. 为什么服务器端需要进行bind绑定IP和端口号,而客户端不需要。
答:服务器端不用bind绑定IP和端口号,直接listen,然后accept,此时会默认自动分配IP和端口号,但是会导致客户端找不到服务器端。客户端没有bind,就会自动分配IP和端口号。
用学术一点的话来讲就是:
当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address familyAF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。
通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。
服务器端代码:
// LinuxServer.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 =