本项目主要是初探网络编程中socket的工作流程,如下图。
socket()函数,无论是服务端还是客户端都需要的函数,它通过系统调用创建一个socket套接字,然后返回一个整型类型的socket描述符(错误的时候会返回-1)。
bind()函数,服务端需要的函数,它可以将套接字和机器上一定的端口关联起来(如果想用listen()来侦听一定端口的数据,这是必要一步)。
listen()函数,服务端需要的函数,它是等待接入请求的第一步。
accept()函数,服务端需要的函数,它是等待接入请求的第二步,是阻塞函数,直到有连接接入,程序才会往下走。他会返回一个新的socket描述符,用于后续的发送和接收。
recv()函数,服务端和客户端都需要的函数,用于流式套接字或者数据报套接字的通讯(如果用无连接的数据报套接字,则应该用recvfrom())。它用于接收数据,函数返回一个实际接收数据的字节数。
send()函数,服务端和客户端都需要的函数,用于流式套接字或者数据报套接字的通讯(如果用无连接的数据报套接字,则应该用sendto())。 它用于发送数据,函数返回一个实际发送数据的字节数。
close()函数,可用于关闭套接字的描述符指向的套接字。
connect()函数,客户端需要的函数,已知目标对象的套接字后,可通过此函数连接目标主机的端口。
直接上服务端和客户端的代码,服务端是一个centos云服务器,客户端是window主机,注释也算是很详尽了。
https://github.com/wohoholor/ChatRoom
谈谈主要思想:
在服务器端的代码主要是这样的,在主线程里创建套接字,将套接字绑定服务器的端口,开始监听。然后执行死循环,死循环里主要是accept()这个堵塞函数,一旦accept到客户端的连接,往存储用户信息的链表里插入一个新的用户,并且立刻创建一个子线程用于和该用户的收发信息(相当于每多一个用户就多一个线程,所以应该要限制用户数量,创建过多的线程可能会使系统崩溃)。还有要注意的点就是,在使用存储用户下信息的链表时,要注意线程安全,避免同时读写。
在客户端的代码就稍微简单点,在主线程里先请用户输入昵称然后存储起来,接着用服务器IP和端口信息创建套接字,然后用此套接字和服务器connect,一旦connect成功就先发送用户昵称,接着创建接收消息的子线程,主线程开始死循环等待用户输入,一旦用户完成输入就将将消息发给服务器,在等待输入期间,一旦子线程接收到消息也会打印出来。
最终效果:
参考内容:
https://www.cnblogs.com/DCD112358/p/10522172.html
https://www.cnblogs.com/kefeiGame/p/7246942.html(关于sockaddr和sockaddr_in,以及函数详解可参考它