一、C语言实现一个简易的client/server聊天工具
在ubuntu平台上,采用c语言实现一个简易的client/server聊天工具,思路是:
服务器端:首先创建一个服务器进程,该进程监听客户端的连接,如果收到并建立连接后创建一个线程服务该客户端。该线程负责消息的转发(这里为了方便直接对消息进行广播)。
客户端:客户端进程首先创建一个线程用于消息接收处理,然后为用户提供信息输入的交互界面。
主要调用栈:
int socket( int domain, int type, int protocol)
- 功能:创建一个新的套接字,返回套接字描述符
- 参数说明:
- domain:域类型,指明使用的协议栈,如TCP/IP使用的是 PF_INET
- type: 指明需要的服务类型, 如
- SOCK_DGRAM: 数据报服务,UDP协议
- SOCK_STREAM: 流服务,TCP协议
- protocol:一般都取0
- 举例:s=socket(PF_INET,SOCK_STREAM,0)
int connect(int sockfd,struct sockaddr *server_addr,int sockaddr_len)
- 功能: 同远程服务器建立主动连接,成功时返回0,若连接失败返回-1。
- 参数说明:
- Sockfd:套接字描述符,指明创建连接的套接字
- Server_addr:指明远程端点:IP地址和端口号
- sockaddr_len :地址长度
int bind(int sockfd,struct sockaddr * my_addr,int addrlen)
- 功能:为套接字指明一个本地端点地址TCP/IP协议使用sockaddr_in结构,包含IP地址和端口号,服务器使用它来指明熟知的端口号,然后等待连接
- 参数说明:
- Sockfd:套接字描述符,指明创建连接的套接字
- my_addr:本地地址,IP地址和端口号
- addrlen :地址长度
- 举例:bind(sockfd, (struct sockaddr *)&address, sizeof(address));
int listen(int sockfd,int input_queue_size)
- 功能:
- 面向连接的服务器使用它将一个套接字置为被动模式,并准备接收传入连接。用于服务器,指明某个套接字连接是被动的
- 参数说明:
- Sockfd:套接字描述符,指明创建连接的套接字
- input_queue_size:该套接字使用的队列长度,指定在请求队列中允许的最大请求数
- 举例:listen(sockfd,20)
int accept(int sockfd, void *addr, int *addrlen);
- 功能:获取传入连接请求,返回新的连接的套接字描述符。为每个新的连接请求创建了一个新的套接字,服务器只对新的连接使用该套接字,原来的监听套接字接受其他的连接请求。新的连接上传输数据使用新的套接字,使用完毕,服务器将关闭这个套接字。
- 参数说明:
- Sockfd:套接字描述符,指明正在监听的套接字
- addr:提出连接请求的主机地址
- addrlen:地址长度
- 举例:new_sockfd = accept(sockfd, (struct sockaddr *)&address, &addrlen);
int send(int sockfd, const void * data, int data_len, unsigned int flags)
- 功能:在TCP连接上发送数据,返回成功传送数据的长度,出错时返回-1。send会将外发数据复制到OS内核中
- 参数说明:
- sockfd:套接字描述符
- data:指向要发送数据的指针
- data_len:数据长度
- flags:一直为0
- 举例(p50):send(s,req,strlen(req),0);
int recv(int sockfd, void *buf, int buf_len,unsigned int flags);
- 功能:从TCP接收数据,返回实际接收的数据长度,出错时返回-1。服务器使用其接收客户请求,客户使用它接受服务器的应答。如果没有数据,将阻塞,如果收到的数据大于缓存的大小,多余的数据将丢弃。
- 参数说明:
- Sockfd:套接字描述符
- Buf:指向内存块的指针
- Buf_len:内存块大小,以字节为单位
- flags:一般为0
- 举例:recv(sockfd,buf,8192,0)
close(int sockfd);
- 功能:撤销套接字。如果只有一个进程使用,立即终止连接并撤销该套接字,如果多个进程共享该套接字,将引用数减一,如果引用数降到零,则撤销它。
- 参数说明:
- Sockfd:套接字描述符
- 举例:close(socket_descriptor)
二、服务器端源代码:
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <string.h> 4 #include <sys/types.h> 5 #include <sys/socket.h> 6 #include <netinet/in.h> 7 #include <arpa/inet.h> 8 #include <unistd.h> 9 10 int client_sockfd[100] = {0};//客户端套接字 11 int count = 0; 12 13 void* clientThreadLoop(void* local) 14 { 15 char buf[BUFSIZ]; //数据传送的缓冲区 16 17 //printf("线程启动 "); 18 int socket_id = *(int *)local; 19 while(1) 20 { 21 memset(buf,0x00,sizeof(buf)); 22 int len=recv(socket_id,buf,BUFSIZ,0); 23 /*接收客户端的数据并将其发送给客户端--recv返回接收到的字节数,send返回发送的字节数*/ 24 if(len > 0) 25 { 26 buf[len]='