Вы распечатываете мусор, потому что recv
не завершает нуль вашего буфера.
Важным разделом в приведенном ниже коде является:
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0); // <<-- Nice to have.
send(client, buffer, num, 0);
buffer[num] = '\0'; // <<-- Really important bit!
if (buffer[num-1] == '\n') // <<-- Nice to have.
buffer[num-1] = '\0'; // <<-- Nice to have.
cout << buffer << endl;
, который будет надлежащим образом завершите свой буфер перед тем, как его распечатать, а также удалите завершающую новую строку, если она есть (и разрешите клиенту различать входные и эхо-строки).
Этот (полная программа) работает немного лучше:
using namespace std;
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 1000
#define PORT 1234
int main() {
char buffer[BUFSIZE];
// define our address structure, stores our port
// and our ip address, and the socket type, etc..
struct sockaddr_in addrinfo;
addrinfo.sin_family = AF_INET;
addrinfo.sin_port = htons(PORT);
addrinfo.sin_addr.s_addr = INADDR_ANY;
// create our socket.
int sock;
if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) {
cout << "Error in creating the socket.";
return -1;
}
// bind our socket to the actual adress we want
if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
cout << "Error in binding.";
return -1;
}
// open the socket up for listening
if (listen(sock, 5) != 0) {
cout << "Error in opening listener.";
return -1;
}
char *msg = "Success! You are connected.\r\n";
// continuously accept new connections.. but no multithreading.. yet
while(1) {
cout << "Waiting for connections...." << endl;
struct sockaddr_in client_addr;
socklen_t sin_size = sizeof(client_addr);
if(int client =
accept(sock, (struct sockaddr*)&client_addr, &sin_size))
{
cout << "Recieved new connection from "
<< inet_ntoa(client_addr.sin_addr) << endl;
send(client, msg, strlen(msg), 0);
while(1) {
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0);
send(client, buffer, num, 0);
buffer[num] = '\0';
if (buffer[num-1] == '\n')
buffer[num-1] = '\0';
cout << buffer << endl;
strcpy(buffer, "");
}
} else {
cout << "Error in accepting new connection." << endl;
}
}
close(sock);
return 0;
}
На стороне клиента:
$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Success! You are connected.
hello
>> hello
my name is pax
>> my name is pax
and you?
>> and you?
<CTRL-D>
Connection closed by foreign host.
и на стороне сервера:
$ ./testprog
Waiting for connections....
Recived new connection from 127.0.0.1
hello
my name is pax
and you?
Waiting for connections....
Определение языка R удобно для ответов на следующие типы вопросов:
R имеет три основных оператора индексации, синтаксис которых показан в следующих примерах.
x [i] х [i, j] х [[i]] х [[i, j]] x $ a x $ "а"Для векторов и матриц формы
[
используются редко, хотя они имеют некоторые незначительные семантические отличия от формы[
) (например, она удаляет все атрибуты name или dimnames, и что частичное соответствие используется для символьных индексов). При индексировании многомерных структур с одним индексомx [[i]]
илиx [i]
вернетi
-й последовательный элемент] х
.Для списков обычно используется
[[
] для выбора любого отдельного элемента, тогда как[
возвращает список выбранных элементов.Форма
[[
] позволяет выбрать только один элемент с использованием целочисленных или символьных индексов, тогда как[
позволяет индексировать по векторам. Однако обратите внимание, что для списка индекс может быть вектором, и каждый элемент вектора применяется по очереди к списку, выбранному компоненту, выбранному компоненту этого компонента и так далее. В результате по-прежнему остается единственный элемент.
Двойные скобки обращаются к элементу списка , а одиночные скобки возвращают список с единственным элементом.
lst <- list('one','two','three')
a <- lst[1]
class(a)
## returns "list"
a <- lst[[1]]
class(a)
## returns "character"
[]
извлекает список, [[]]
извлекает элементы в списке
alist <- list(c("a", "b", "c"), c(1,2,3,4), c(8e6, 5.2e9, -9.3e7))
str(alist[[1]])
chr [1:3] "a" "b" "c"
str(alist[1])
List of 1
$ : chr [1:3] "a" "b" "c"
str(alist[[1]][1])
chr "a"
Существенные различия между двумя методами заключаются в классе объектов, которые они возвращают при использовании для извлечения, и в том, могут ли они принимать диапазон значений или только одно значение во время присвоения.
Рассмотрим случай извлечения данных в следующем списке:
foo <- list( str='R', vec=c(1,2,3), bool=TRUE )
Допустим, мы хотели бы извлечь значение, хранящееся в bool, из foo и использовать его внутри оператора if ()
. Это продемонстрирует различия между возвращаемыми значениями []
и [[]]
, когда они используются для извлечения данных. Метод []
возвращает объекты списка классов (или data. frame, если foo был data.frame), а метод [[]]
возвращает объекты, класс которых определяется типом их значений.
Таким образом, использование метода []
приводит к следующему:
if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical
class( foo[ 'bool' ] )
[1] "list"
Это потому, что метод []
возвратил список, а список не является допустимым объектом для передачи непосредственно в if ()
заявление. В этом случае нам нужно использовать [[]]
, потому что он вернет "пустой" объект, хранящийся в 'bool', который будет иметь соответствующий класс:
if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"
class( foo[[ 'bool' ]] )
[1] "logical"
Второе отличие состоит в том, что []
может использоваться для доступа к диапазону слотов в списке или столбцам в кадре данных, в то время как оператор [[]]
ограничен доступом к одиночному слот или столбец. Рассмотрим случай присвоения значений с использованием второго списка, bar ()
:
bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )
Допустим, мы хотим перезаписать последние два слота foo данными, содержащимися в bar. Если мы попытаемся использовать оператор [[]]
, произойдет следующее:
foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar :
more elements supplied than there are to replace
Это потому, что [[]]
ограничен доступом к одному элементу. Нам нужно использовать []
:
foo[ 2:3 ] <- bar
print( foo )
$str
[1] "R"
$vec
[,1] [,2]
[1,] 0 0
[2,] 0 0
$bool
[1] -0.6291121
Обратите внимание, что, хотя присвоение было успешным, слоты в foo сохранили свои оригинальные имена.