Beachten Sie, dass ich Schwierigkeiten hatte, mit dem Ruby TCP-Server und dem C-Client zu kommunizieren.
Infolgedessen bestand das Problem darin, dass die Einheiten der Menge an scheinbaren Daten, die Ruby und C an den Stream gesendet und empfangen haben, unterschiedlich waren. Aus diesem Grund haben wir die Sputs-Funktion und die Sgets-Funktion implementiert, die C-Schreib- und Lesefunktionen umschließen, damit sie in derselben Einheit wie Ruby kommunizieren können.
Die Umwelt ist
ist.
Es ist ein Server, der die Kommunikation startet und die vom Client empfangene Zeichenfolge fast so zurückgibt, wie sie ist. Wiederholen Sie dies 5 Mal, um den Vorgang abzuschließen.
server.rb
require 'socket'
#Starten Sie den Server an Port 20000
server = TCPServer.open(20000)
#Kommunikation akzeptieren
sock = server.accept
5.times do
#Empfangen Sie eine Zeile aus dem Puffer.(Erhalten Sie bis zum Zeilenumbruch)
line = sock.gets.chomp
#Wird auf der Konsole angezeigt. Wenn es p ist, ist es auch null\Es wird als x00 angezeigt.
p line
#Rückkehr. Am Ende\n wird hinzugefügt.
sock.puts("you sent <<<#{line}>>>.")
end
#Trennen Sie die Kommunikation
sock.close
Implementieren Sie die Sputs- und Sgets-Funktionen für Rubys Gets und Puts.
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define RECV_SIZE (10000)
#define SEND_SIZE (10000)
/*
*Holen Sie sich eine Zeile aus dem Puffer.(get string from stream)
*Wenn sich keine Daten für eine Zeile im Puffer befinden, warten Sie.
*/
char* sgets(int sd, char* line) {
//Der Teil, der vor dem letzten Zeilenumbruch herausgenommen wurde
static char* read_buf = NULL;
if (read_buf == NULL) {
read_buf = malloc(sizeof(char) * RECV_SIZE);
read_buf[0] = '\0';
}
while (1) {
int e;
if (strlen(read_buf) != (e = strcspn(read_buf, "\n"))) {
//Zeile initialisieren
memset(line, '\0', sizeof(char) * strlen(line));
//Kopieren Sie eine Zeile in Zeile
strncpy(line, read_buf, (e + 1) - 0);
//Lesen Sie die nächste Zeile_Kopie vom Anfang von buf
strcpy(read_buf, strchr(read_buf, '\n') + 1);
break;
}
//Initialisieren und bereiten Sie ein Array für den Empfang vor
char r[RECV_SIZE] = { 0 };
//Erhält die gerade gesendete Zeichenmenge aus dem Puffer.(Kein nachfolgendes NULL)
if (read(sd, r, sizeof(r) * RECV_SIZE) < 0) {
perror("recv");
fflush(0);
return NULL;
}
//Sammeln Sie die gelesenen Daten.
strcat(read_buf, r);
}
return line;
}
/*
*Senden Sie eine Zeile.(put string to stream)
*Am Ende"\n"Hinzugefügt.
*/
void sputs(int sd, char* str) {
char* send_str = malloc(sizeof(char) *(strlen(str) + 2));
memset(send_str, '\0', sizeof(char) *(strlen(str) + 2));
strcat(send_str, str);
send_str[strlen(str)] = '\n';
if (write(sd, send_str, sizeof(char) * strlen(send_str)) < 0) {
perror("send");
return;
}
free(send_str);
}
int main(int argc, char *argv[]) {
int sd; //Variablen zum Erstellen von Sockets
struct sockaddr_in addr; //Variablen für die Serververbindung
char *recv[sizeof(char) * RECV_SIZE] = {0};
//Erstellen Sie einen Socket für IPv4-TCP
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return -1;
}
//Stellen Sie die Zieladresse und die Portnummer ein
addr.sin_family = AF_INET;
addr.sin_port = htons(20000);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Serververbindung (für TCP müssen Sie eine Verbindung herstellen)
connect(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
char* strs[5] = {"abcde", "fg", "hijklmn", "opqrs", "tuvwxyz"};
for(int i = 0; i < 5; i++) {
//Senden Sie eine Zeile. Am Ende\n wird hinzugefügt.
sputs(sd, strs[i]);
//Holen Sie sich eine Zeile.
sgets(sd, recv);
//Anzeige
printf("I recived <<<%s>>>\n", recv);
}
//Steckdose schließen
close(sd);
return 0;
}
Seien Sie vorsichtig mit der in sgets verwendeten Lesefunktion. Der Inhalt des Puffers wird mit read (sd, r, sizeof (r) * RECV_SIZE) in r geschrieben, aber die Funktion read liest das Ende der Zeichenkette nicht gut, sondern 1 Byte. Schreiben Sie jedes Mal bis zu dem Punkt auf, den Sie erhalten haben. Außerdem wird am Ende des Schreibens keine Null hinzugefügt. Daher wird empfohlen, r jedes Mal mit null zu füllen.
Beachten Sie auch die Schreibfunktion, die in Sputs verwendet wird. Wenn Sie "write (sd, send_str, sizeof (char) * strlen (send_str)" mit einer großen Anzahl von dritten Argumenten verwenden und auf "SEND_SIZE" setzen, werden SEND_SIZE-Bytes unabhängig von der Länge der Zeichenfolge des zweiten Arguments gesendet. Es scheint, dass der fehlende Teil mit NULL gefüllt ist.
Übrigens ist die Implementierung, die nicht gut funktioniert, wie folgt.
client.c(Schlechtes Beispiel)
int main(int argc, char *argv[]) {
int sd; //Variablen zum Erstellen von Sockets
struct sockaddr_in addr; //Variablen für die Serververbindung
char *recv[sizeof(char) * RECV_SIZE] = {0};
//Erstellen Sie einen Socket für IPv4-TCP
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return -1;
}
//Stellen Sie die Zieladresse und die Portnummer ein
addr.sin_family = AF_INET;
addr.sin_port = htons(20000);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Serververbindung (für TCP müssen Sie eine Verbindung herstellen)
connect(sd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
char* strs[5] = {"abcde", "fg", "hijklmn", "opqrs", "tuvwxyz"};
for(int i = 0; i < 5; i++) {
//Senden Sie eine Zeile.
write(sd, strs[i], SEND_SIZE);
//Holen Sie sich eine Zeile.
read(sd, recv, RECV_SIZE);
//Anzeige
printf("I recived <<<%s>>>\n", recv);
}
//Steckdose schließen
close(sd);
return 0;
}
Schreiben Lesen und Schreiben mit dem gleichen get und Puts Gefühl, wie Ruby scheitern wird.
$ ruby server.rb
$ gcc -O2 -o client client.c
$ ./clinet
Serverseite
"abcde\n"
"fg\n"
"hijklmn\n"
"opqrs\n"
"tuvwxyz\n"
Client-Seite
I recived <<<you sent <<<abcde>>>.
>>>
I recived <<<you sent <<<fg>>>.
>>>
I recived <<<you sent <<<hijklmn>>>.
>>>
I recived <<<you sent <<<opqrs>>>.
>>>
I recived <<<you sent <<<tuvwxyz>>>.
>>>
In C wird es nicht in eine Zeichenkette wie Ruby konvertiert, daher musste ich bei der byteweisen Verarbeitung vorsichtig sein. Wenn eine TCP-Kommunikation zwischen anderen Sprachen durchgeführt wird, treten wahrscheinlich verschiedene Probleme aufgrund der unterschiedlichen Handhabung der Kommunikation auf.
Recommended Posts