刚开始接触网络编程,学了一些内容之后,就像学着做一些项目,所以想实现一个简单的聊天室项目,完成服务器和客户端简单的交流,一开始知识有限,我就是用的socket连接客户端和服务器,然后使用send和recv函数实现了客户端和服务器简单的交流。
server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main( int argc , char* argv[])
{
char msg[1000]="\0";
int serverSock , connectingSock;
struct sockaddr_in serverAddr, client_addr;
socklen_t addrlen , client_addr_size;
serverSock = socket( AF_INET , SOCK_STREAM , IPPROTO_TCP);
if( serverSock <0)
{
puts("socket建立失败");
exit(1);
}
addrlen = sizeof(serverAddr);
memset( &serverAddr , 0 , addrlen);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(3333);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if( bind( serverSock , (struct sockaddr*)&serverAddr , sizeof(serverAddr) )<0)
{
puts("绑定IP 地址到socket失败");
exit(1);
}
if(listen( serverSock , 10 ))
{
puts("设置socket为监听状态失败");
}
puts("等待客户端连接...");
client_addr_size = sizeof(client_addr);
connectingSock = accept( serverSock , (struct sockaddr*)&client_addr , &client_addr_size);
if( connectingSock <0 )
{
puts("处理连接时发生错误");
}
while(1){
char send_msg[200] = "\0";
puts("请输入聊天内容");
scanf("%s", send_msg);
if( send( connectingSock , send_msg, strlen(send_msg ) , 0) <=0 )
{
puts("发送消息失败");
}else{
puts("发送消息成功");
}
memset( msg , 0 , 1000) ;
if ( recv( connectingSock , msg , 999 , 0) <= 0 )
{
puts("接收消息失败");
}else{
puts( msg);
}
}
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
void error_handling(char *message);
int main( int argc , char* argv[])
{
char msg[1000] = "\0";
int client_sock ;
struct sockaddr_in client_addr ,server_addr;
int addrlen, strlen ;
char message[20];
client_sock = socket( AF_INET , SOCK_STREAM , IPPROTO_TCP);
if( client_sock <0)
{
puts("socket建立失败");
exit(1);
}
puts("socket成功建立");
addrlen = sizeof(client_addr);
memset( &client_addr , 0 , addrlen);
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(3333);
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(client_sock, (struct sockaddr*)&client_addr, sizeof(client_addr)) == -1)
error_handling("connect error");
while(1){
memset( msg , 0 , 1000) ;
if ( recv( client_sock , msg , 999 , 0) <= 0 )
{
puts("接收消息失败");
}else{
puts( msg);
}
char send_msg[200] = "\0";
puts("请输入聊天内容");
scanf("%s", send_msg);
if( send( client_sock , send_msg, sizeof(send_msg) , 0) <=0 )
{
puts("发送消息失败");
}else{
puts("发送消息成功");
}
}
//return 0;
}
void error_handling(char * message){
puts(message);
exit(1);
}
运行结果图如下:
但是以上代码有个明显的弊端,就是代码最佳体现形式就是服务器和客户端轮流发送消息,否则的话就不会有最佳的效果,就会出现发送延迟的情况,所以我学习了进程间通讯,学习了 管道 和 消息队列 的有关知识。于是将以上代码进行了改进,我增加了父子进程,得以让服务器和客户端较为方便的实现通讯。
server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main( int argc , char* argv[])
{
char msg[1000] = "\0";
int serverSock , connectingSock;
struct sockaddr_in serverAddr, client_addr;
socklen_t addrlen , client_addr_size;
serverSock = socket( AF_INET , SOCK_STREAM , IPPROTO_TCP);
if( serverSock <0)
{
puts("socket建立失败");
exit(1);
}
addrlen = sizeof(serverAddr);
memset( &serverAddr , 0 , addrlen);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(3333);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if( bind( serverSock , (struct sockaddr*)&serverAddr , sizeof(serverAddr) )<0)
{
puts("绑定IP 地址到socket失败");
exit(1);
}
if(listen( serverSock , 10 ))
{
puts("设置socket为监听状态失败");
}
puts("等待客户端连接...");
client_addr_size = sizeof(client_addr);
connectingSock = accept( serverSock , (struct sockaddr*)&client_addr , &client_addr_size);
if( connectingSock <0 )
{
puts("处理连接时发生错误");
}
pid_t pid;
pid = fork();
if(pid > 0){
char send_msg[200] = "\0";
while(1){
memset(send_msg, 0, 1000);
scanf("%s", send_msg);
if( send( connectingSock , send_msg, strlen(send_msg ) , 0) <=0 ) {
puts("发送消息失败");
}
else{
puts("发送消息成功");
}
}
}
if(pid == 0){
while(1){
if ( recv( connectingSock , msg , 999 , 0) <= 0 ) {
puts("接收消息失败");
}
else{
puts( msg);
}
memset(msg, 0, sizeof(msg));
}
}
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
void error_handling(char *message);
int main( int argc , char* argv[])
{
char msg[1000] = "\0";
int client_sock ;
struct sockaddr_in client_addr ,server_addr;
int addrlen;
char message[20];
int a = 0;
client_sock = socket( AF_INET , SOCK_STREAM , IPPROTO_TCP);
// printf("%d",a);
if( client_sock <0)
{
puts("socket建立失败");
exit(1);
}
puts("socket成功建立");
addrlen = sizeof(client_addr);
memset( &client_addr , 0 , addrlen);
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(3333);
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(client_sock, (struct sockaddr*)&client_addr, sizeof(client_addr)) == -1)
error_handling("connect error");
pid_t pid;
pid = fork();
if(pid == 0){
char send_msg[200] = "\0";
while(1){
memset(send_msg, 0, 1000);
scanf("%s", send_msg);
if( send( client_sock , send_msg, strlen(send_msg ) , 0) <=0 ) {
puts("发送消息失败");
}
else{
puts("发送消息成功");
}
}
}
if(pid > 0){
while(1){
if ( recv ( client_sock, msg , 999 , 0) <= 0 ) {
puts("接收消息失败");
}
else{
puts( msg);
}
memset(msg, 0, sizeof(msg));
}
}
}
void error_handling(char * message){
puts(message);
exit(1);
}
运行结果如下:
这里就较好的处理了只能轮流发消息的问题,使代码实用性更高。
进行了如此项目之后,我想对一个服务器能和多少个客户端进行链接进行研究,因此,我修改了客户端的代码
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
void error_handling(char *message);
int main( int argc , char* argv[])
{
char msg[1000] = "\0";
int client_sock ;
struct sockaddr_in client_addr ,server_addr;
int addrlen;
char message[20];
int a = 0;
while(1){//***
client_sock = socket( AF_INET , SOCK_STREAM , IPPROTO_TCP);
if( client_sock <0)
{
puts("socket建立失败");
exit(1);
}
puts("socket成功建立");
addrlen = sizeof(client_addr);
memset( &client_addr , 0 , addrlen);
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(3333);
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(client_sock, (struct sockaddr*)&client_addr, sizeof(client_addr)) == -1)
error_handling("connect error");
printf("%d\n", ++a);//***
}
pid_t pid;
pid = fork();
if(pid == 0){
char send_msg[200] = "\0";
while(1){
scanf("%s", send_msg);
memset(send_msg, 0, 1000);
if( send( client_sock , send_msg, strlen(send_msg ) , 0) <=0 ) {
puts("发送消息失败");
}
else{
puts("发送消息成功");
}
}
}
if(pid > 0){
while(1){
if ( recv ( client_sock, msg , 999 , 0) <= 0 ) {
puts("接收消息失败");
}
else{
puts( msg);
}
memset(msg, 0, 1000);
}
}
}
void error_handling(char * message){
puts(message);
exit(1);
}
仅仅就加入了注释为“***”的两条语句,然后经过运行客户端和服务器,运行结果如下图所示:
所以在我的电脑上,一个服务器可以链接12个客户端,也欢迎大家试一下自己的电脑一个服务器可以连接多少个客户端哦!
欢迎在评论区提问评论哦!