寫了一個簡單的服務器軟件,但是沒有寫客戶端。現在我將客戶端實現了,其實昨天已經說了客戶端的實現步驟了。
步驟:
- socket()
- 初始化
- connet()鏈接
- 從標準輸入讀數據fgets()
- 傳數據到服務器write()
- 讀從服務器返回的數據read()
- 寫數據到屏幕上write()
- 關閉socket文件close()
都沒有什么新知識的。所以我也就直接貼代碼了;
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define ADDR_POST 9527
int main(void)
{
????int c_fd; //客戶端的socket文件描述符
????int len; //從服務器傳回的字符串長度
????char buf[BUFSIZ]; //儲存數據
????struct sockaddr_in clie_addr; //客戶端地址結構體
????socklen_t addr_len; //客戶端地址結構體大小
?
????//創建客戶端socket文件,指定IPV4 ,TCP協議
????c_fd = socket(AF_INET,SOCK_STREAM,0);
?
????//初始化客戶端地址結構體
????inet_pton(AF_INET, "127.0.0.1", &clie_addr.sin_addr.s_addr);//將IP字符串轉化為網絡值存入其中,這個"127.0.0.1"就是客戶端的IP,但不一定是公網IP
????clie_addr.sin_family = AF_INET;//指定IPV4協議族
????clie_addr.sin_port = htons(ADDR_POST);//將服務器的端口轉化為網絡值存入
?
????connect(c_fd, (struct sockaddr*)&clie_addr, sizeof(clie_addr));//由地址結構體連接服務器;
????//因為地址結構體中有服務器的端口,端口在機器上是唯一的。
????//剛接觸,其實有很多還是不大明白。我們的服務器軟件和客戶端軟件都是運行在一臺機器上的,一臺機器中的端口號是唯一的,類似進程號。至于若是服務器軟件和客戶端位于不同的機器是怎么經過網絡找到對應的機器,我就不大清楚了,以后學到了在解惑吧。
?
????while (1)
????{
????????fgets(buf, sizeof(buf), stdin); //從標準輸入中讀取數據
????????write(c_fd, buf, strlen(buf)); //寫到服務器中c_fd既有接收端又有發送端。
????????len = read(c_fd, buf, sizeof(buf)); //讀從服務器返回的數據
????????write(STDOUT_FILENO, buf, len); //寫到屏幕上
????}
????close(c_fd);
?
????return 0;
}
其實很簡單的。
結果和昨天的示例一樣:。服務器依然是阻塞著的,沒啥好看的。
由于客戶端不需要固定的端口號,因此不必調用bind(),客戶端的端口號由內核自動分配。注意,客戶端不是不允許調用bind(),只是沒有必要調用bind()固定一個端口號,服務器也不是必須調用bind(),但如果服務器不調用bind(),內核會自動給服務器分配監聽端口,每次啟動服務器時端口號都不一樣,客戶端要連接服務器就會遇到麻煩。
客戶端和服務器啟動后可以使用netstat命令查看鏈接情況:
netstat -apn|grep 6666