c - C中的套接字:客户端无法接收和打印从服务器发送的字符串数组
问题描述
我编写套接字程序,即客户端向服务器发送一个字符串数组,服务器接收该数组并发送回客户端。我的服务器可以在服务器端成功打印出字符串数组 reply[] 。但是,在客户端,它无法打印出结果。这是我的代码
客户端.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define PORT 4444
int main(int argc, char *argv[]){
if (argc < 2 || argc > 3) // Test for correct number of arguments
printf("Parameter(): <Server Address>");
char *servIP = argv[1]; // arg: server IP address (dotted quad)
int clientSocket, ret;
struct sockaddr_in serverAddr; // Server address
char buffer[1024];
char **reply = malloc(20*sizeof(char *));
// Create a reliable, stream socket using TCP
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Client Socket is created.\n");
// Construct the server address structure
memset(&serverAddr, '\0', sizeof(serverAddr)); // Zero out structure
serverAddr.sin_family = AF_INET; // IPv4 address family
serverAddr.sin_port = htons(PORT); // Server port
// Convert address
int rtnVal = inet_pton(AF_INET, servIP, &serverAddr.sin_addr.s_addr);
if (rtnVal == 0)
printf("inet_pton() failed: invalid address string");
else if (rtnVal < 0)
printf("inet_pton() failed");
// Establish the connection to the sorted server
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Connected to Server.\n");
//Read arrays from input file
FILE *fptr;
fptr = fopen("client1.inputdat", "r"); //open input file to read
if (fptr != NULL)
{
int line =0;
while(fgets(buffer, sizeof(buffer), fptr)) { //read line by line of the input file
line++;
if (line==1) {
printf("\n");
printf("Unsorted array: %s\n", buffer);
// Send arrays to the server
send(clientSocket, buffer, strlen(buffer), 0);
// Receive the sorted arrays back from the server
if(recv(clientSocket, &reply, 20*sizeof(char *), 0) < 0){
printf("Error in receiving data.\n");
}
else {
int i;
printf("Sorted array:");
for (i=0; i<20; i++) {
reply[i] = malloc(10*sizeof(char));
printf("%s ", reply[i]);
}
}
}
}
fclose(fptr);
}
else {
printf("File does not exits");
exit(1);
}
return 0;
}
服务器.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
int main(){
int sockfd, ret;
struct sockaddr_in serverAddr; // Local address
int newSocket;
struct sockaddr_in newAddr;
socklen_t addr_size;
char buffer[1024];
pid_t childpid;
// Create socket for incoming connections
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Server Socket is created.\n");
// Construct local address structure
memset(&serverAddr, '\0', sizeof(serverAddr)); // Zero out structure
serverAddr.sin_family = AF_INET; // IPv4 address family
serverAddr.sin_port = htons(PORT); // Local port
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface
// Bind to the local address
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in binding.\n");
exit(1);
}
printf("Bind to port %d\n", 4444);
// Mark the socket so it will listen for incoming connections
if(listen(sockfd, 10) == 0){ //Maximum outstanding connection requests is 10
printf("Listening....\n");
}else{
printf("Error in binding.\n");
}
while(1){
// Wait for clients to connect
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
// newSocket is connected to client!
char newName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &newAddr.sin_addr.s_addr, newName, sizeof(newName)) != NULL)
printf("Handling client %s/ %d\n", newName, ntohs(newAddr.sin_port));
else
printf("Unable to get client address");
//Handle concurrency by using fork
if((childpid = fork()) == 0){
close(sockfd);
while(1){
recv(newSocket, buffer, 1024, 0);
int i=0;
char *array[20];
char **reply = malloc(20*sizeof(char *));
char *p = strtok(buffer, ",");
while (p!=NULL) {
array[i++] = p;
p = strtok(NULL, ","); //stroke received string into tokens
}
for (i=0; i<20; i++) {
reply[i] = malloc(10*sizeof(char));
strcpy(reply[i], array[i]); //input tokens into array
printf("%s ", reply[i]);
}
send(newSocket, reply, 20*sizeof(char *), 0);
bzero(reply, sizeof(reply));
//}
}
}
}
close(newSocket);
return 0;
}
那么,我该如何解决这个问题,以便客户端可以打印出从服务器发送的数组回复 []?谢谢推荐
解决方案
好的。您的代码清楚地表明您不太了解 C,更不用说套接字,但这是一个新的改进版本,我认为它可以满足您的需求。我的大部分改进都包含在对原始帖子的评论中。我没有在所有合适的地方检查错误,这在许多其他方面远非完美,但这会做一些看起来像你想要的事情而不会爆炸。
您正在发送数据,却不知道您是否收到了所有已传输的数据。套接字是流。它以最方便的方式发送数据,而不是您可能喜欢的方式。为了解决这个问题,我要求我们\n
在每次传输时发送一个。\n
每次从另一端取回数据时,我们都会检查并继续读取数据。在我发送了许多回复数据后,我发送了一个\n
字符,以便客户端知道已收到整行。我们不需要\n
从客户端添加,因为在缓冲区的末尾fgets
留下了。\n
你提到排序是额外的好处,我添加了一个qsort
来排序数据。在compReply
函数中,我不只是直接从 the 返回值,strcmp
而是将其放入 anint
中,以便在必要时在调试器中看到它。我相信一些编译器会抱怨我在做strcmp
两个void *
变量。为了整洁,您可能希望在将它们(char*)a
传递给strcmp
.
我删除了您fork
以使其更易于调试。抱歉,这一次只允许一个连接。当我写这样的东西时,我通常不会派生一个新进程,而是有一个 newSocket 值数组并select
用来决定从哪个值读取。(该select
函数也可以使用accept
。)同样,这种方式更容易调试。
该strtok
函数将找到的字符替换为 null 并返回指向字符串开头的指针。我只是想删除不需要的字符,所以我使用它而不费心接受返回值。这也可以通过以下方式完成:
char *p=strchr(buffer,'\n');
if( NULL != p ) *p=0;
但是strtok
更简洁。
我允许将端口号传递给服务器,但没有将其添加到客户端。那好吧。
我在让客户端运行之前测试了服务器
telnet 127.0.0.1 4444
并输入:a,s,d,f,g,h,j,k,l <CR>
要取回已排序的列表a,d,f,g,h,j,k,l,s,
,我也不喜欢尾随逗号,但我现在不会让它消失。
服务器:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
#define BUF_SIZE 1024
static int compReply(const void *a, const void *b)
{
int ret=strcmp(a,b);
return(ret);
}
int main(int argc, char *argv[])
{
int port=4444;
int sockfd, ret;
struct sockaddr_in serverAddr; // Local address
int newSocket;
struct sockaddr_in newAddr;
socklen_t addr_size;
if( argc > 1 ) {
port=atoi(argv[1]);
if( port < 1024 ) {
port=4444;
}
}
// Create socket for incoming connections
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Server Socket is created.\n");
// Construct local address structure
memset(&serverAddr, '\0', sizeof(serverAddr)); // Zero out structure
serverAddr.sin_family = AF_INET; // IPv4 address family
serverAddr.sin_port = htons(PORT); // Local port
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // Any incoming interface
// Bind to the local address
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in binding.\n");
perror("bind");
exit(1);
}
printf("Bind to port %d\n", port);
// Mark the socket so it will listen for incoming connections
if(listen(sockfd, 10) == 0){ //Maximum outstanding connection requests is 10
printf("Listening....\n");
}else{
printf("Error in listening.\n");
perror("listen");
}
while(1){
// Wait for clients to connect
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
// newSocket is connected to client!
char newName[INET_ADDRSTRLEN]; // String to contain client address
if (inet_ntop(AF_INET, &newAddr.sin_addr.s_addr, newName, sizeof(newName)) != NULL)
printf("Handling client %s/ %d\n", newName, ntohs(newAddr.sin_port));
else
printf("Unable to get client address");
while(1){
char buffer[BUF_SIZE]={0};
int ret=1;
int count=0;
while(NULL == strchr(buffer,'\n') && ret > 0 && count < sizeof(buffer))
{
ret=recv(newSocket, &buffer[count], sizeof(buffer)-count, 0);
count+=ret;
}
if( ret <= 0 ) {
if( ret < 0 ) {
printf("Problem with recv: %d\n", ret);
}
break;
}
printf("recv: %s\n", buffer);
strtok(buffer,"\n\r"); /* throw away any \r\n */
if( ret> 0 ) {
int i=0;
char reply[20][BUF_SIZE]={0};
char *p = strtok(buffer, ",");
while (p!=NULL) {
strncpy(reply[i],p,BUF_SIZE);
strcat(reply[i],",");
p = strtok(NULL, ","); //stroke received string into tokens
i++;
}
qsort(reply,i,BUF_SIZE,compReply);
for(int jj=0; jj<i; jj++) {
printf("%s ", reply[jj]);
ret=send(newSocket, reply[jj], strlen(reply[jj]), 0);
}
ret=send(newSocket, "\n", 1, 0);
printf("\n");
}
}
close(newSocket);
}
return 0;
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define PORT 4444
#define BUF_SIZE 1024
int main(int argc, char *argv[])
{
char servIP[120]="127.0.0.1";
if( argc > 1 ) {
strncpy(servIP,argv[1],sizeof(servIP));
}
int clientSocket, ret;
struct sockaddr_in serverAddr; // Server address
char buffer[BUF_SIZE];
// Create a reliable, stream socket using TCP
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Client Socket is created.\n");
// Construct the server address structure
memset(&serverAddr, '\0', sizeof(serverAddr)); // Zero out structure
serverAddr.sin_family = AF_INET; // IPv4 address family
serverAddr.sin_port = htons(PORT); // Server port
// Convert address
int rtnVal = inet_pton(AF_INET, servIP, &serverAddr.sin_addr.s_addr);
if (rtnVal == 0)
printf("inet_pton() failed: invalid address string");
else if (rtnVal < 0)
printf("inet_pton() failed");
// Establish the connection to the sorted server
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Connected to Server.\n");
//Read arrays from input file
FILE *fptr;
fptr = fopen("this.csv", "r"); //open input file to read
if (fptr != NULL) {
while(fgets(buffer, sizeof(buffer), fptr)) //read line by line of the input file
{
char reply[BUF_SIZE]={0};
char repList[20][BUF_SIZE]={0};
int count=0;
int ret=1;
printf("Unsorted array: %s", buffer);
// Send array to the server
send(clientSocket, buffer, strlen(buffer), 0);
// Receive the sorted arrays back from the server
while(NULL == strchr(reply,'\n') && ret > 0 && count < sizeof(reply))
{
ret=recv(clientSocket, &reply[count],sizeof(reply)-count,0);
count+=ret;
}
if( ret < 0 ) {
printf("Error in receiving data.\n");
}
else {
int i=0;
strtok(reply,"\n\r");
for(char *p=strtok(reply,",");p!=NULL; p=strtok(NULL,","))
{
strncpy(repList[i],p,BUF_SIZE);
i++;
}
printf("Sorted array:");
for (int jj=0; jj<i; jj++) {
printf("%s ", repList[jj]);
}
}
printf("\n");
}
fclose(fptr);
}
else {
printf("File does not exist");
perror("fopen");
exit(1);
}
return 0;
}
这应该给你一些尝试让你继续前进。我希望它有所帮助。
推荐阅读
- python - globals() 函数在 python 中有奇怪的行为
- python - 如何将输入限制为一系列数字?
- visual-studio-code - 错误 FS0010:在此点或之前绑定的结构化构造不完整
- c# - 当 Wi-Fi 信号/连接较低时做一些事情 ASP .NET Core
- c# - C# 在 Lambda 表达式中使用来自反射的 PropertyInfo,错误:不是有效的属性表达式
- javascript - 提示时 Node JS 生成输入文本
- powershell - Powershell Invoke-WebRequest 的问题
- installation - 在 UAC 提示后,Installshield installscript 安装程序终止
- javascript - TypeError:无法读取未定义的属性“凭据”-React-redux-firebase,Firebase Auth
- html - 如何在 MSSQL 数据库中高效地存储 HTML 内容