[問題] Socket接收資料處理

作者: TampaBayRays (光芒今年拿冠軍)   2018-11-10 10:08:40
開發平台(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
感謝!
作者: bigbite (子子孫孫永保用)   2018-11-10 11:01:00
斷行也被傳進去了, 改成strncmp(buffer,"ls", 2)
作者: s4300026 (s4300026)   2018-11-10 11:35:00
不是啊,你應該送的時候就把/n處理掉啊,因為你不能保證n=recv會傳幾個,如果一次只傳一個怎辦?而不是在收的地方做line的substr的處理那你應該去看client送出前的字串你按enter總是會有接受的buffer吧,在那buffer把/n處理掉那你printf(%d %s, n,buffer)recv後直接印最原始的buffer宣告時 ={}Is/n 另一個猜不出來 /0?char buffer[maxlen] ={};不是啊,你要去看你收到什麼東西,才能做處理,如果你要收到什麼,就回傳什麼,那這樣寫沒問題,但是如果你想要判斷收到的內容,不是應該收完再處理嗎? 也就是要跳出while再處理問題http://beej-zhtw.netdpi.net/07-advanced-technology/7-2-select整串收完再做判斷,去看總共收到什麼,才去掉不想要的東西然後buffer初始化清零是我想表達的重點是 recv不會一次收完全部的訊息,假設你傳 1234567890,但收到的可能會是 1234、567890
作者: Bencrie   2018-11-10 13:12:00
你確定對方 send 會幫你送 \0 嗎
作者: JJJJoe (毛毛)   2018-11-10 13:27:00
可以先 line.length() 看看長度多少,如果是 3 的話代表有收到 \0還有 Mac OS 預設的換行符是 \r,所以才會有蓋掉第一個字元的情形\r 代表的是返回到該行開頭的意思,因此單引號就會回到該行的開頭印出,就蓋掉原本的字元了我建議使用 line=line.substr(0,line.length()-1) 來處理話說回來 每個系統換行符不同,在其他系統 telnet 結果可能會不一樣?你是在substr之後才print的嗎?一般來說不會有這個結果@@所以你一開始說length=3是在line=line.substr(0,n-1)還是line=line.substr(0,n)之後?我是指我一開始問的時候,還沒有使用line.length()-1我覺得收到的四個字元應該是 ls\r\n 才會有這種情況那我猜的沒錯,line.length()-2 應該就行了順便問一下你目前 clinet 是在哪個系統進行的?我想知道的是你是在哪個作業系統下telnet指令的,我不知道每個作業系統有沒有差別echo 的訊息如果有換行,就表示有印出\r\n喔喔 看來每個系統的telnet在訊息結尾都會加上\r\n學到一課了XD

Links booklink

Contact Us: admin [ a t ] ucptt.com