[問題] Socket接收資料處理
看板C_and_CPP (C/C++)作者TampaBayRays (光芒今年拿冠軍)時間7年前 (2018/11/10 10:08)推噓19(19推 0噓 26→)留言45則, 4人參與討論串1/1
開發平台(Platform): (Ex: Win10, Linux, ...)
Mac OS Mojave
編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
G++
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
問題(Question):
我做了一個server想接收client的指令去執行,但是我將指令傳到
server時,server無法判斷指令,所以我先做了一個小程式,把收到的指令印出來,
並判斷他是不是ls,結果還是不行
餵入的資料(Input):
ls
預期的正確結果(Expected Output):
印出recevied:'ls'
yes
錯誤結果(Wrong Output):
server:
client connected with ip address: 0.0.0.0
received: 'ls
'
received: 'ls
'
client:
telnet 0.0.0.0 8877
Trying 0.0.0.0...
Connected to 0.0.0.0.
Escape character is '^]'.
ls
ls
程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔)
int main(int argc, char *argv[]) {
int SERVER_PORT = 8877;
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(SERVER_PORT);
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
int listen_sock;
if ((listen_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
printf("could not create listen socket\n");
return 1;
}
if ((bind(listen_sock, (struct sockaddr *)&server_address,sizeof(server_address))) < 0) {
printf("could not bind socket\n");
return 1;
}
int wait_size = 16; // maximum number of waiting clients, after which
// dropping begins
if (listen(listen_sock, wait_size) < 0) {
printf("could not open socket for listening\n");
return 1;
}
struct sockaddr_in client_address;
socklen_t client_address_len = 0;
while (true) {
int sock;
if ((sock =accept(listen_sock, (struct sockaddr *)&client_address, &client_address_len)) < 0) {
printf("could not open a socket to accept data\n");
return 1;
}
int n = 0;
int len = 0, maxlen = 100;
char buffer[maxlen];
char *pbuffer = buffer;
printf("client connected with ip address: %s\n",inet_ntoa(client_address.sin_addr));
while ((n = recv(sock, pbuffer, maxlen, 0)) > 0) {
pbuffer += n;
maxlen -= n;
len += n;
printf("received: '%s'\n", buffer);
string line=buffer;
line=line.substr(0,n);
printf("received: '%s'\n", line.c_str());
if (!strcmp(buffer,"ls")){
printf("yes");
}
if (line=="ls"){
printf("yes");
}
send(sock, buffer, len, 0);
}
close(sock);
}
close(listen_sock);
return 0;
}
補充說明(Supplement):
看起來傳回去的東西是沒問題的,但是為什麼我server收到的東西不太對。
1.右括號被換行了
2.沒有判斷出我傳的是ls(應該要印出yes)
請各位大大救救我QQ
感謝!
--
╭ ◢█◤ ╭══╮ ╭ ◢█ ◣ theanswer3╮
║ █▌╰═════════════════╯ ★ ╰══╯ █▌ █ ╴◤ / ║
║ ◢█◣ ◢█◣ ◢█◣ ◢█◣ ◢◢◣ ◢ ◢█◣ ◢ ◤  ̄╱> ║
║ █▌ ◢ █▌█ ███ █▌█ █▌█ █◤ █ █◢█ ◥ ◣ ║
║◢███◤◥█◤ ◥▌◤ ◥██ ◥█◤ █ ◤ ◥◤◥ █▌ █ ╰/ ║
╰═════════════▅◤═════════════ ◥█ ◤ ═════╯
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.127.199.39
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1541815726.A.2E0.html
→
11/10 11:01,
7年前
, 1F
11/10 11:01, 1F
我也覺得是這樣,所以我有用一個string line去接,然後line=line.substr(0,n),
如果是這樣那感覺第二個yes應該會印出來?
然後如果我改成line=line.substr(0,n-1)那會變成印出
client connected with ip address: 0.0.0.0
received: 'ls
'
'eceived: 'ls
我無法理解為什麼右括號會蓋掉第一個字母.....
推
11/10 11:35,
7年前
, 2F
11/10 11:35, 2F
→
11/10 11:35,
7年前
, 3F
11/10 11:35, 3F
可是我是用telnet 0.0.0.0 port這樣去連我的server,我不知道他為什麼會把/n
傳過來
推
11/10 11:37,
7年前
, 4F
11/10 11:37, 4F
雖然不應該這樣處理,但是處理了還不行就更崩潰XD
還是我telnet的使用方法錯誤,我是打一行指令然後按enter傳送到server。
推
11/10 11:40,
7年前
, 5F
11/10 11:40, 5F
推
11/10 11:43,
7年前
, 6F
11/10 11:43, 6F
→
11/10 11:43,
7年前
, 7F
11/10 11:43, 7F
可是我沒有寫client,我是在終端機打telnet 0.0.0.0 port直接連我的server,
而且我server echo回去的訊息看起來也沒有/n
※ 編輯: TampaBayRays (111.251.137.40), 11/10/2018 11:45:47
推
11/10 11:51,
7年前
, 8F
11/10 11:51, 8F
→
11/10 11:52,
7年前
, 9F
11/10 11:52, 9F
這樣會出現
client connected with ip address: 0.0.0.0
4 ls
'eceived: 'ls
收到4個字元...?
client的echo:
telnet 0.0.0.0 8878
Trying 0.0.0.0...
Connected to 0.0.0.0.
Escape character is '^]'.
ls
ls
推
11/10 12:05,
7年前
, 10F
11/10 12:05, 10F
推
11/10 12:07,
7年前
, 11F
11/10 12:07, 11F
我把buffer宣告改成
char buffer[]={};
然後就換變成
client connected with ip address: 0.0.0.0
4 lo
'eceived: 'lo
client:
telnet 0.0.0.0 8878
Trying 0.0.0.0...
Connected to 0.0.0.0.
Escape character is '^]'.
ls
lo
好像更慘了
求解QQ
推
11/10 12:19,
7年前
, 12F
11/10 12:19, 12F
好像不行這樣
variable-sized object may not be initialized
int maxlen
※ 編輯: TampaBayRays (111.251.137.40), 11/10/2018 12:22:13
推
11/10 12:22,
7年前
, 13F
11/10 12:22, 13F
→
11/10 12:22,
7年前
, 14F
11/10 12:22, 14F
→
11/10 12:22,
7年前
, 15F
11/10 12:22, 15F
→
11/10 12:22,
7年前
, 16F
11/10 12:22, 16F
→
11/10 12:22,
7年前
, 17F
11/10 12:22, 17F
→
11/10 12:22,
7年前
, 18F
11/10 12:22, 18F
我現在做的只有單一client,想要做到的事是client連上來輸入一行指令,
server就回傳這行指令執行結果,然後在收下一行指令,傳回下一行指令執行結果,
直到client斷線
推
11/10 12:25,
7年前
, 19F
11/10 12:25, 19F
→
11/10 12:25,
7年前
, 20F
11/10 12:25, 20F
→
11/10 12:26,
7年前
, 21F
11/10 12:26, 21F
推
11/10 12:28,
7年前
, 22F
11/10 12:28, 22F
→
11/10 12:28,
7年前
, 23F
11/10 12:28, 23F
1.我希望做的是有互動的感覺,所以希望是一是收一行指令
2.這個我之前有加上 memset (&buffer, 0, maxlen) ;我覺得應該是一樣的意思?
但是還是沒用
3.這個我知道,但是我才傳兩個char,而且看起來應該是有收到完整指令,如果真的
是這個問題,請問要怎麼處理呢?
※ 編輯: TampaBayRays (111.251.137.40), 11/10/2018 12:32:56
推
11/10 13:12,
7年前
, 24F
11/10 13:12, 24F
推
11/10 13:27,
7年前
, 25F
11/10 13:27, 25F
→
11/10 13:27,
7年前
, 26F
11/10 13:27, 26F
→
11/10 13:28,
7年前
, 27F
11/10 13:28, 27F
→
11/10 13:28,
7年前
, 28F
11/10 13:28, 28F
length是3,另外我加上了
cout<<(line.find("\0")!=string::npos)<< " "<<(line.find("\n")!=string::npos)
<<(line.find("\r")!=string::npos)<<endl;
結果印出來是101
另外可以請問Mac OS預設換行符是\r就會有蓋掉第一個字元的情況發生呢?
※ 編輯: TampaBayRays (111.251.137.40), 11/10/2018 13:46:26
推
11/10 13:49,
7年前
, 29F
11/10 13:49, 29F
→
11/10 13:49,
7年前
, 30F
11/10 13:49, 30F
→
11/10 13:51,
7年前
, 31F
11/10 13:51, 31F
→
11/10 13:54,
7年前
, 32F
11/10 13:54, 32F
→
11/10 13:55,
7年前
, 33F
11/10 13:55, 33F
我改用line=line.substr(0,line.length()-1)結果還是一樣會印出
'eceived: 'ls
line size:3
1 01
我之前是用ubuntu的telnet結果也是一樣....
推
11/10 14:27,
7年前
, 34F
11/10 14:27, 34F
我現在的while裡面長這樣
while ((n = recv(sock, pbuffer, maxlen, 0)) > 0) {
pbuffer += n;
maxlen -= n;
len += n;
printf("%d %s", n,buffer);
printf("received: '%s'\n", buffer);
string line=buffer;
line=line.substr(0,line.length()-1);
printf("received: '%s'\n", line.c_str());
cout<<"line size:"<<line.length()<<endl;
cout<<(line.find("\0")!=string::npos)
<<(line.find("\n")!=string::npos)
<<(line.find("\r")!=string::npos)<<endl;
if (!strcmp(buffer,"ls")){
printf("yes");
}
if (line=="ls"){
printf("yes");
}
send(sock, buffer, len, 0);
memset (&buffer, 0, maxlen) ;
}
然後傳ls會印出
client connected with ip address: 0.0.0.0
4 ls
received: 'ls
'
'eceived: 'ls
line size:3
1 01
我發現直接印出來不會有換行,可是前後加東西一起印就會有,
難道是char[]跟string之間轉換有什麼要注意的地方嗎?
不是string=char[]直接傳就可以嗎?
還是我在一開始設定socket的時候有什麼參數設定錯了?
推
11/10 15:11,
7年前
, 35F
11/10 15:11, 35F
→
11/10 15:11,
7年前
, 36F
11/10 15:11, 36F
我在這裡把length印出來
cout<<"line size:"<<line.length()<<endl;
在line=line.substr(0,line.length()-1);之後
→
11/10 15:15,
7年前
, 37F
11/10 15:15, 37F
推
11/10 15:24,
7年前
, 38F
11/10 15:24, 38F
line=line.substr(0,n-1)後length是3
推
11/10 15:29,
7年前
, 39F
11/10 15:29, 39F
→
11/10 15:30,
7年前
, 40F
11/10 15:30, 40F
真的可以了!!!!!
感謝大大!!!!!!
我沒有client,我是在終端機打telnet 0.0.0.0 port直接去連我的server
可是我server ehco回去的沒有\r\n,所以telnet在收到東西後會自己切掉,
可是傳的時候不會?
我的系統是Mac OS Mojave跟Ubuntu 16.04直接用終端機的telnet連都會有上面的問題
推
11/10 15:44,
7年前
, 41F
11/10 15:44, 41F
→
11/10 15:44,
7年前
, 42F
11/10 15:44, 42F
→
11/10 15:44,
7年前
, 43F
11/10 15:44, 43F
→
11/10 15:47,
7年前
, 44F
11/10 15:47, 44F
→
11/10 15:47,
7年前
, 45F
11/10 15:47, 45F
我在Mac OS跟Ubuntu的終端機用telnet連我的server,傳過去都會有\r\n,
但是echo回去印出來的都沒有換行,所以感覺是telnet再送的時候會送\r\n過來,
然後收到的時候會自己把它切掉。
終於解決這個問題了,感謝大大的幫忙!!!!!
※ 編輯: TampaBayRays (111.251.137.40), 11/10/2018 16:04:15
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章