米志志 发表于 2012-11-01 14:58

才疏学前,关于socket通信的问题,求指导

小弟不才,浅学socket。我是写一个cs模式,(server精灵挂起)
server接收client的数字表达式字符串,然后进行计算后回发结果给client,
当初发现在client端按Ctrl+c后,发现server也同时断开,然后逛了一下论坛,才知道是sigpipe,用大神教的方法解决了。
然后自己再想想,能不能在client端发个结束标志?
代码如下
server端:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <memory.h>
#include <signal.h>
int exit_code = 0;
extern void* recv_thread(void*p);
void handle_pipe(int sig){}
int main()
{
      pid_t pid1;
      if(pid1=fork()==0)
      {
                setsid();
                chdir("/";
                close(0);close(1);close(2);
                umask(0);
      //1.创建sonket
      int sockfd = socket(PF_INET,SOCK_STREAM,0);
      if(sockfd == -1)perror("",exit(-1);
      //2.准备地址
      struct sockaddr_in addr;
      addr.sin_family = PF_INET;
      addr.sin_port = htons(12345);
      inet_aton("127.0.0.1",&addr.sin_addr);
      //3.绑定
      int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
      if(res == -1)perror("绑定失败",exit(-1);
      printf("绑定成功!\n";
      //4.监听
      if( listen(sockfd,100)==-1)
                perror("监听失败!",exit(-1);
      printf("监听启动\n";

      while(1)
                {
      //5.等待客户端连接   len必须赋值
      struct sockaddr_in fromaddr;
      socklen_t len = sizeof(fromaddr);
      int fd = accept(sockfd,(struct sockaddr*)&fromaddr,&len);
      if(fd == -1)
                perror("accept失败";
      else
                printf("有客户端连接服务器\n";

      struct sigaction action;
      action.sa_handler = handle_pipe;
      sigemptyset(&action.sa_mask);
      action.sa_flags = 0;      
      sigaction(SIGPIPE,&action,NULL);
      
      
      //6.通信      
      pthread_t pid;
      pthread_create(&pid,0,recv_thread,&fd);
      pthread_join(pid,0);
                }
               
      }                                          //精灵      
//      close(sockfd);
}

/*******************************/

void* recv_thread(void*q)
{
      int fds = *(int*)q;
while(1)
{
      double sum =0;
      char a = {0};
      double shuzi = {0};
      char fuhao = {0};
      read(fds,a,sizeof(a));
      printf("客户说:%s\n",a);
      if(*a=='q'||*a=='Q')                                    \
      {
      sum = 88;                                                       \
      write(fds,&sum,;                                           ---- >检查结束标志
      break;                                                             /
      }                                                                      /
      int flag = 0;
      int i,j=0,k=0;
      static int p;

//字符转整形部分      
      for(i=0; a!='\0'; i++)
      {
                if(a=='*'||a=='/'||a=='+'||a=='-'||a=='=')
                {
                        fuhao = a;
                        k++;
                        a = '\n';
                        shuzi = atoi(a+p);
//                        printf("%d ",shuzi);
                        j++;
                        p = i;
                        continue;
                }
      }
//检查部分
      for(flag=0; flag<j; flag++)
      {
                printf("%.2lf ",shuzi);
                printf("%c ",fuhao);
      }                                                   
      printf("\n";
//乘除运算部分
      int success;      
//      double* temp = (double*)malloc(sizeof(double)*100);
      double temp = {0};
//      double sum =0;
      success = 0;
      for(i=0; i<k-1;i++)
      {
                if(fuhao=='*')
                {
                        int z = 0;
                        flag = 0;
                        for(z=j-1; z>i-1; z--)
                        {
                              temp = shuzi;
                              shuzi = 0;
                              flag++;
                        }
                        flag = flag - 1;
                        sum = temp*temp;

                         /*重构数字数组*/
                        shuzi = sum;
                        printf("%d %d %d\n",flag,j,i);
                        for(z=i+1; z<j-1; z++,flag--)   
                        {      shuzi = temp;}
                        for(z=0; z<j-1; z++)
                        {      printf("%d ",shuzi);}
                        j--;
                        success = 1;
                }
                if(fuhao=='/')
                {
                        int z = 0;
                        flag = 0;
                        for(z=j-1; z>i-1; z--)
                        {
                              temp = shuzi;
                              shuzi = 0;
                              flag++;
                        }
                        flag = flag - 1;
                        sum = temp/temp;

                         /*重构数字数组*/
                        shuzi = sum;
                        printf("%d %d %d\n",flag,j,i);
                        for(z=i+1; z<j-1; z++,flag--)   
                        {      shuzi = temp;}
                        for(z=0; z<j-1; z++)
                        {      printf("%.2lf ",shuzi);}
                        j--;
                        success = 1;
                }
                /*重构符号数组*/
                if(success == 1)
                {
                        int f;
                        for(f=i; f<j; f++){
                        fuhao = fuhao;
                        printf("%c ",fuhao);
                        }
                        k--;
                        success = 0;
                        i = i - 1;
                }
      }
      printf("\n%.2lf\n",sum);
      write(fds,&sum,;
      p = 0;      
      memset(a,0,100);
      memset(shuzi,0,100);
      memset(fuhao,0,100);
      memset(temp,0,100);
}
close(fds);
return ((void*)exit_code);
}

/*************************************************************/
client端

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
int main()
{

      //1.创建sonket
      int sockfd = socket(PF_INET,SOCK_STREAM,0);
      if(sockfd == -1)perror("",exit(-1);
      //2.准备地址
      struct sockaddr_in addr;
      addr.sin_family = PF_INET;
      addr.sin_port = htons(12345);
      inet_aton("127.0.0.1",&addr.sin_addr);
      //3.连接
      int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
      if(res == -1)perror("connect失败"),exit(-1);
      printf("连接成功!\n");
      
while(1)
{
      char arg = {0};
      printf("输入运算表达式:");
      scanf("%s",arg);
      printf("%s",arg);                                             <------为啥没反应?
      if(arg=='q') printf("退出!\n"),exit(0) ;          <------为啥没反应?
      //6.通信
      double sum =0;
      write(sockfd,arg,strlen(arg));
      read(sockfd,&sum,;
      printf("服务器运算结果说:%.2lf\n",sum);

}
      printf("!!!!!!!!\n");
      //7.关闭
      close(sockfd);
}

按q后发现,server断开与client的通信,但是client不能反悔shell界面。server端使用了线程,是不是线程问题?还是内存问题?
求大神知道!

linux_c_py_php 发表于 2012-11-01 15:13

自己close自己的socket之后再写socket才会出SIGPIPE, 说实话这种错误永远也不应该发生,发生了就要反思自己的代码。

lxyscls_cu 发表于 2012-11-02 09:15

注册一个信号处理函数——SIGTERM(即CTRL-C)

在该信号函数中使用shutdown关闭写端,可以继续读

米志志 发表于 2012-11-02 09:46

谢谢指点,其实ctrl-c的问题我已经解决,现在的问题是对离开标志‘q’   
为什么客户端没响应,而服务端就有响应

米志志 发表于 2012-11-02 09:46

回复 3# lxyscls_cu




谢谢指点,其实ctrl-c的问题我已经解决,现在的问题是对离开标志‘q’   
为什么客户端没响应,而服务端就有响应

   

lxyscls_cu 发表于 2012-11-02 12:47

本帖最后由 lxyscls_cu 于 2012-11-02 12:48 编辑

{:3_189:}

zj47596731 发表于 2012-11-02 16:58

奇怪 用楼主的代码 我怎么能退出到shell啊...

xbokx 发表于 2012-11-04 09:27

汗,可以用子进程来实现吧
页: [1]
查看完整版本: 才疏学前,关于socket通信的问题,求指导