Socket網路程式設計(1) ———— 基於TCP協議的客戶-伺服器socket例項
阿新 • • 發佈:2019-01-22
Socket網路程式設計(1)
———— 基於TCP協議的客戶-伺服器socket例項
1、TCP網路程式設計架構
2、程式碼段
- 伺服器:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8888 /*偵聽埠地址*/
#define BACKLOG 2 /*偵聽佇列長度*/
int main(int argc, char *argv[])
{
int ss,sc; /*ss為伺服器的socket描述符,sc為客戶端的socket描述符*/
struct sockaddr_in server_addr; /*伺服器地址結構*/
struct sockaddr_in client_addr; /*客戶端地址結構*/
int err; /*返回值*/
pid_t pid;
char words[1024]; /*分叉的進行ID*/
/*建立一個流式套接字*/
ss = socket(AF_INET, SOCK_STREAM, 0);
if(ss < 0){ /*出錯*/
printf("socket error\n");
return -1;
}
/*設定伺服器地址*/
bzero(&server_addr, sizeof(server_addr)); /*清零*/
server_addr.sin_family = AF_INET; /*協議族*/
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地地址*/
server_addr.sin_port = htons(PORT); /*伺服器埠*/
/*繫結地址結構到套接字描述符*/
err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(err < 0){/*出錯*/
printf("bind error\n");
return -1;
}
/*設定偵聽*/
err = listen(ss, BACKLOG);
if(err < 0){ /*出錯*/
printf("listen error\n");
return -1;
}
/*主迴圈過程*/
for(;;) {
socklen_t addrlen = sizeof(struct sockaddr);
sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen);
/*接收客戶端連線*/
if(sc < 0){ /*出錯*/
continue; /*結束本次迴圈*/
}else{
sprintf(words, "%d login\n", sc);
write(1, words, strlen(words)+1);
}
/*建立一個新的程序處理到來的連線*/
pid = fork(); /*分叉程序*/
if( pid == 0 ){ /*子程序中*/
//process_conn_server(sc); /*處理連線*/
ssize_t size = 0;
char buffer[1024]; /*資料的緩衝區*/
for(;;){ /*迴圈處理過程*/
size = read(sc, buffer, 1024); /*從套接字中讀取資料放到 緩衝區buffer中*/
if(size == 0){ /*沒有資料*/
return;
}
write(1, buffer, size); /*寫到標準輸出*/
sprintf(buffer, "From %d\n", sc);
write(1, buffer, strlen(buffer)+1); /*寫到標準輸出*/
/*構建響應字元,為接收到客戶端位元組的數量*/
sprintf(buffer, "I receive %d bytes altogether\n", size);
write(sc, buffer, strlen(buffer)+1);/*發給客戶端*/
}
close(ss); /*在子程序中關閉伺服器的偵聽*/
}else{
//close(sc); /*在父程序中關閉客戶端的連線*/
}
}
}
- 客戶端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8888 /*偵聽埠地址*/
#define IP "127.0.0.1" /*伺服器IP地址*/
int main(int argc, char *argv[])
{
int s; /*s為socket描述符*/
struct sockaddr_in server_addr; /*伺服器地址結構*/
s = socket(AF_INET, SOCK_STREAM, 0); /*建立一個流式套接字 */
if(s < 0){ /*出錯*/
printf("socket error\n");
return -1;
}
/*設定伺服器地址*/
bzero(&server_addr, sizeof(server_addr)); /*清零*/
server_addr.sin_family = AF_INET; /*協議族*/
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地地址*/
server_addr.sin_port = htons(PORT); /*伺服器埠*/
/*將使用者輸入的字串型別的IP地址轉為整型*/
inet_pton(AF_INET, IP, &server_addr.sin_addr);
/*連線伺服器*/
connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
//process_conn_client(s); /*客戶端處理過程*/
ssize_t size = 0;
char buffer[1024]; /*資料的緩衝區*/
for(;;){ /*迴圈處理過程*/
/*從標準輸入中讀取資料放到緩衝區buffer中*/
size = read(0, buffer, 1024);
if(size > 0){ /*讀到資料*/
write(s, buffer, size); /*傳送給伺服器*/
size = read(s, buffer, 1024); /*從伺服器讀取資料*/
write(1, buffer, size); /*寫到標準輸出*/
}
}
close(s); /*關閉連線*/
return 0;
}
- makefile:
all:client server clean #all規則,它依賴於client和server規則
client: tcp_client.o #client規則,生成客戶端可執行程式
gcc -o client tcp_client.o
server: tcp_server.o #server規則,生成伺服器端可執行程式
gcc -o server tcp_server.o
clean: #清理規則,刪除client、server和中間檔案
rm -f tcp_process tcp_client tcp_server *.o
3、效果展示
伺服器
不同客戶端連線,會顯示不同id登入,當傳送資訊時,也會顯示是來自哪個客戶端。客戶端
兩個客戶端的連線,當傳送資訊時,會受到伺服器的返回,顯示收到的字元數