• 主页
  • 系统维护与使用
  • 应用程序开发
  • 内核源代码
  • 驱动程序开发
  • CPU和硬件区
  • UNIX文化
  • Solaris
  • Power Linux
抽搐人偶师0 2020年04月19日
新手请教一个Linux下一个C语言socket编程的问题
想要使用socket实现一个双向通信。然后任意一方输入quit就可以退出,最开始我实现的是单向的服务器发送消息客户端接收消息,我的功能可以正常实现退出。后来我使用fork实现双向通信以后,输入quit就不能正常退出了,会卡住。只会显示连接关闭但是没办法回到命令提示符,这时候如果继续输入就会卡住,对方也不会接收到这段消息,但是如果我把对方的shell关掉,那么我就会回到命令行下,刚才输入的内容就会被逐行当作命令执行,到底是怎么回事呢??求个解释,截图如下:

代码如下:
server.c
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<unistd.h>

#define MYPORT 3490 //侦听端口号
#define BACKLOG 100 //侦听队列长度
#define MAXDATASIZE 1024 //一次可以读的最大的字节数

int main(int argc, char* argv[])
{
int serverfd; //服务器socket套接字描述符
int communicationfd = 0; //双方通信描述符
int link = 0; //连接状态,根据accept函数返回值改变,初始未连接时为0
struct sockaddr_in serveraddr; //服务器地址信息
struct sockaddr_in clientaddr; //客户端地址信息
int clientsinsize; //客户端地址信息结构体大小
//1获得服务器套接字描述符
if((serverfd=socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Server Socket Failed!");
exit(1);
}
//2构造服务器的地址信息sockaddr_in
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(MYPORT); //使用网络字节序端口号
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); //网络字节序IP
bzero(&(serveraddr.sin_zero), 8);
//3绑定侦听端口
if(bind(serverfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)) == -1)
{
perror("Server Bind Failed!");
exit(1);
}
//4监听端口
if(listen(serverfd, BACKLOG) == -1)
{
perror("Server Listen Failed!");
exit(1);
}
while(link == 0)
{
//5接受客户端的连接请求
printf("等待连接中......\n");
clientsinsize = sizeof(struct sockaddr_in);
communicationfd = accept(serverfd, (struct sockaddr*)&clientaddr, &clientsinsize);
if(communicationfd == -1)
{
perror("Server Accept faild");
exit(1);
}
if(communicationfd > 0) //accept函数返回值大于0时表示接收了连接请求,返回的即是通信所需要的文件描述符
link = 1;
}
int clientip = clientaddr.sin_addr.s_addr;
printf("Got Connection From %d.%d.%d.%d\n", clientip&255,(clientip>>8)&255,(clientip>>16)&255,(clientip>>24)&255);
printf("现在可以开始通信了!\n");
//主循环,接受连接请求后link值变为1
pid_t fpid; //创建子进程,让它处理和父进程不同的工作
fpid = fork();
while(link==1)
{
if(fpid > 0)
{
//6父进程读取消息
char buf[MAXDATASIZE];
int numbytes = recv(communicationfd, buf, MAXDATASIZE, 0);
if(numbytes == -1)
{
perror("Receive Failed!");
exit(1);
}
else if(numbytes > 0)
{
buf[numbytes] = '\0';
printf("对方(Client)发来的消息: \n");
printf("*****");
printf("%s\n", buf);
}
else
{
printf("对方已经关闭连接!\n");
link = 0;
}
}
else
{
//7子进程发送消息
char msg[1024];
char judge[1024] = "quit";
scanf("%s", msg);
if(strcmp(msg, judge)==0)
{
link = 0;
close(serverfd);
close(communicationfd);
printf("连接已经被关闭!\n");
return 0;
}
else
{
printf("我(Server)发送的消息:\n");
printf("*****");
printf("%s\n", msg);
if(send(communicationfd, msg, 1024, 0) == -1)
{
perror("Send Failed");
continue;
}
}
}
}
return 0;
}

client.c如下:
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<arpa/inet.h>
#include<string.h>
#include<netdb.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<fcntl.h>
#include<unistd.h>

#define PORT 3490
#define MAXDATASIZE 1024 //一次可以读的最大的字节数

int main(int argc, char* argv[])
{
int clientfd, numbytes; //客户端socket描述符和接收到数据大小
int link = 1 ; //表示连接状态,由connect函数赋值,连接时为0,未连接时为1。
char buf[MAXDATASIZE]; //读取的缓冲区
struct sockaddr_in serveraddr; //服务器地址信息结构体
//1创建客户端socket,并获取客户端socket描述符
if((clientfd=socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Client Socket Failed!");
exit(1);
}
//2构造服务器的地址信息sockaddr_in结构
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(PORT); //使用网络字节序端口号
serveraddr.sin_addr.s_addr = inet_addr("192.168.1.101"); //将点分十进制IP地址转化为网络字节序IP
bzero(&(serveraddr.sin_zero), 8);
//3向服务器发起连接
printf("等待服务器响应连接请求......\n");
link = connect(clientfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr));
if(link == -1)
{
perror("Connect Failed!");
exit(1);
}
if(link==0)
printf("已经成功连接至服务器!\n");
else
printf("与服务器连接失败!\n");
//将connect函数返回值赋给link,为0则表示连接成功,开始读取缓冲区内容
pid_t fpid; //创建子进程,让它处理和父进程不同的工作
fpid = fork();
while(link==0)
{
if(fpid > 0)
{
//4父进程读取消息
numbytes = recv(clientfd, buf, MAXDATASIZE, 0);
if(numbytes == -1)
{
perror("Receive Failed!");
exit(1);
}
else if(numbytes > 0)
{
buf[numbytes] = '\0';
printf("对方(Server)发来的消息: \n");
printf("*****");
printf("%s\n", buf);
}
else
{
printf("对方已经关闭连接!\n");
link = 1;
}
}
else
{
//5子进程用来发送消息
char msg[1024];
char judge[1024] = "quit";
scanf("%s", msg);
if(strcmp(msg, judge)==0)
{
close(clientfd);
printf("连接已经被关闭!\n");
link = 1;
}
else
{
printf("我(Client)发送的消息:\n");
printf("*****");
printf("%s\n", msg);
if(send(clientfd, msg, 1024, 0) == -1)
{
perror("Send Failed");
continue;
}
}
}
}
return 0;
}
...全文
210 点赞 收藏 10
写回复
10 条回复

还没有回复,快来抢沙发~

发动态
发帖子
Linux/Unix社区
创建于2007-08-27

7019

社区成员

7.3w+

社区内容

Linux/Unix社区 应用程序开发区
社区公告
暂无公告