2010-03-03 227 views
0

我已经写了一个客户端和服务器c程序,我已经从示例代码中获得了。c程序客户端服务器

我想写一个迭代的客户端和服务器程序, 即客户端后,发送一个字符串,然后服务器打印该字符串,然后返回一个字符串,客户端

然后在客户端打印由服务器输入的字符串等等,直到客户端输入'退出'退出。

我修改了客户端和服务器是迭代

此外,如果客户端输入“退出”,程序将退出

但是我有一个问题的代码,我不知道该怎么使客户端接收由服务器inputed字符串,我只能让服务器接收客户端的字符串

请随时提供线索

非常感谢!

我的代码

client.c

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <string.h> 
#include <stdarg.h> 
#include <winsock2.h> 

#define SA struct sockaddr 
#define S_PORT 4321 
#define BufferStoreLEN 1024 

void errexit(const char *format, ...) 
{ 
     va_list args; 
     va_start(args, format); 
     vfprintf(stderr, format, args); 
     va_end(args); 
     WSACleanup(); 
     exit(1); 
} 

int main(int argc, char **argv) 
{ 
     WSADATA wsadata; 
     SOCKET sockfd, listenfd, connfd; 
     int i, n, q, len, alen, out; 
     char str[BufferStoreLEN+1]; 
     char cmp[] = "exit"; 
     char* BufferStore; 
     struct sockaddr_in servaddr, cliaddr; 

     if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) 
       errexit("WSAStartup failed\n"); 

     if (argc != 2) 
       errexit("wrong arg"); 

     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 
       errexit("socket error: error number %d\n", WSAGetLastError()); 

     memset(&servaddr, 0, sizeof(servaddr)); 
     servaddr.sin_family = AF_INET; 
     servaddr.sin_port = htons(S_PORT); 
     if ((servaddr.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE) 
       errexit("inet_addr error: error number %d\n", WSAGetLastError()); 

     if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR) 
       errexit("connect error: error number %d\n", WSAGetLastError()); 

     do { 
       printf("Input: "); 
       scanf("%s", str); 
       out = htonl(strlen(str)); 
       BufferStore = malloc(strlen(str)); 
       for(i=0; i<strlen(str); i++) 
         BufferStore[i] = str[i]; 
       out = send(sockfd, BufferStore, strlen(str), 0); 
/*    
       if (strcmp(cmp, str) != 0) 
       { 
         printf("Server's response:\n"); 
         n = recv(connfd, BufferStore, BufferStoreLEN, 0); 

         while (n > 0) { 
           BufferStore[n] = '\0'; 
           printf("%s\n", BufferStore); 
           n = recv(connfd, BufferStore, BufferStoreLEN, 0); 
         } 
       }*/ 
     }while(strcmp(cmp,str)!=0); 

     closesocket(sockfd); 
     WSACleanup(); 
     free(str); 
     free(BufferStore); 
     return 0; 
} 

server.c

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <string.h> 
#include <stdarg.h> 
#include <winsock2.h> 
#include <Windows.h> 
#define SA struct sockaddr 
#define MAXLINE 4096 
#define S_PORT 4321 
#define BufferStoreLEN 1024 

void errexit(const char *format, ...) 
{ 
     va_list args; 
     va_start(args, format); 
     vfprintf(stderr, format, args); 
     va_end(args); 
     WSACleanup(); 
     exit(1); 
} 

int main(int argc, char **argv) 
{ 

     WSADATA wsadata; 
     SOCKET listenfd, connfd; 
     SOCKET sockfd; 
     int number, out; 
     int i, n, q, alen; 
     struct sockaddr_in servaddr, cliaddr; 
     char BufferStore[BufferStoreLEN+1]; 
     char* Store; 
     char str[BufferStoreLEN+1]; 
     int flag = 1; 

     if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) 
       errexit("WSAStartup failed\n"); 

     listenfd = socket(AF_INET, SOCK_STREAM, 0); 
     if (listenfd == INVALID_SOCKET) 
       errexit("cannot create socket: error number %d\n", WSAGetLastError()); 

     memset(&servaddr, 0, sizeof(servaddr)); 
     servaddr.sin_family  = AF_INET; 
     servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
     servaddr.sin_port  = htons(S_PORT); 

     if (bind(listenfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR) 
       errexit("can't bind to port %d: error number %d\n", S_PORT, WSAGetLastError()); 

     if (listen(listenfd, 5) == SOCKET_ERROR) 
       errexit("can't listen on port %d: error number %d\n", S_PORT, WSAGetLastError()); 

     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 
       errexit("socket error: error number %d\n", WSAGetLastError()); 

     for (; ;) 
     { 
       alen = sizeof(SA); 
       connfd = accept(listenfd, (SA *) &cliaddr, &alen); 
       if (connfd == INVALID_SOCKET) 
         errexit("accept failed: error number %d\n", WSAGetLastError()); 

       n = recv(connfd, BufferStore, BufferStoreLEN, 0); 

       while (n > 0){ 
         BufferStore[n] = '\0'; 
         printf("%s\n", BufferStore); 
         printf("Input: "); 
         scanf("%s",str); 
         out = htonl(strlen(str)); 
         Store = malloc(strlen(str)); 
         for(q=0; q<strlen(str); q++) 
           Store[q] = str[q]; 
         out = send(sockfd, Store, strlen(str), 0); 
         n = recv(connfd, BufferStore, BufferStoreLEN, 0); 
       } 
       closesocket(sockfd); 
       WSACleanup(); 
       free(str); 
       free(BufferStore); 
     } 
} 

回答

0

你的服务器是一个无限循环中运行,所以能够发送的数据被输入服务器应用程序的客户端应用程序,你必须阅读在不同的线程的用户输入,然后发送给用户,作为无限循环当前正在阻止当前线程。

+0

您不需要多个线程在服务器中执行简单的“读取下一个命令,发送响应”循环(以及客户端的反向)。 – 2010-03-03 15:01:36

0

有关流套接字(SOCK_STREAM)的一个重要理解是,它们为您提供了一个字节(因此名称:-)),没有任何“数据包边界”。

具体而言,如果从客户端发送()100个字节的数据,则服务器可以RECV()它作为

  • 一个的recv()调用返回100个字节
  • 2的recv()秒的50个字节,然后10的recv()1个字节
  • 第...等各
  • 一个的recv()90个字节...

您的代码似乎假设你本身是什么一端的nd()将在另一端的单个recv()调用中传递。对于小块数据,这可能有用,但这不是你可以/应该依赖的。

一般来说,做一个命令/响应的场景像你设置,您需要有服务器识别“这是命令,我现在应该响应的结束”的方式。例如,如果您要发送文本字符串,则可以使用换行符(\ n)作为“命令结束”标记。

服务器因而会做多种的recv()调用(每一个附加到一个缓冲器),直到它看到一个\ N(或错误),然后发送回响应;客户在阅读回复时会做类似的事情。