參考:http://www.javashuo.com/article/p-urimmnpq-c.htmlhtml
1.用C語言寫socket和client編程
(1)客戶端向服務器端連續發送三條信息並接收每一次服務器端返回的信息,服務器端每接收到一次消息就向客戶端返回一個ok服務器
socket服務器端:數據結構
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>socket
int main()
{
// 第1步:建立服務端的socket。
int listenfd = socket(AF_INET,SOCK_STREAM,0);//第一個參數表示協議族,AF_INET表示是使用的ipv4。第二個參數指定socket類型,這裏使用SOCK_STREAM流式,是一種適用於tcp協議的雙向通訊。第三個參數通常只寫0。tcp
// 第2步:把服務端用於通訊的地址和端口綁定到socket上。
struct sockaddr_in servaddr; // 服務端地址信息的數據結構。
memset(&servaddr,0,sizeof(servaddr));//初始化結構體
servaddr.sin_family = AF_INET; // 協議族,在socket編程中只能是AF_INET。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
//servaddr.sin_addr.s_addr = inet_addr("118.89.50.198"); // 指定ip地址。
servaddr.sin_port = htons(5051); // 指定通訊端口。
if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )//將上面設置的這個參數結構體綁定到socket上
{ perror("bind"); close(listenfd); return -1; }函數
// 第3步:把socket設置爲監聽模式。
if (listen(listenfd,5) != 0 ) { perror("listen"); close(listenfd); return -1; }3d
// 第4步:接受客戶端的鏈接。
int clientfd; // 客戶端的socket。
int socklen=sizeof(struct sockaddr_in); // struct sockaddr_in的大小
struct sockaddr_in clientaddr; // 客戶端的地址信息。
clientfd=accept(listenfd,(struct sockaddr *)&clientaddr,(socklen_t*)&socklen);//這句代碼會阻塞進程,代碼執行在這裏會一直等待客戶端的鏈接
printf("客戶端(%s)已鏈接。\n",inet_ntoa(clientaddr.sin_addr));指針
// 第5步:與客戶端通訊,接收客戶端發過來的報文後,回覆ok。
char buffer[1024];
while (1)//當客戶端鏈接上來會就一直接收客戶端發的消息
{
memset(buffer,0,sizeof(buffer));
if (recv(clientfd,buffer,sizeof(buffer),0)<=0) break; // 接收客戶端的請求報文。
printf("接收:%s\n",buffer);htm
strcpy(buffer,"ok");
if (send(clientfd,buffer,strlen(buffer),0)<=0) break; // 向客戶端發送響應結果。因爲上面accept的時候獲取到了鏈接上來的這個客戶端socket,因此這裏能夠用這個socket向客戶端返回發送消息
printf("發送:%s\n",buffer);
}
// 第6步:關閉socket,釋放資源。
close(listenfd); close(clientfd);
}
socket客戶端:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
int main()
{
// 第1步:建立客戶端的socket。
int sockfd = socket(AF_INET,SOCK_STREAM,0);
// 第2步:向服務器發起鏈接請求。
struct hostent* h;
if ( (h = gethostbyname("192.168.31.155")) == 0 ) // 指定服務端的ip地址。這個函數用來將字符串的ip地址或域名轉換未一個結構體,返回一個回一個hostent結構指針
{ perror("gethostbyname"); close(sockfd); return -1; }
struct sockaddr_in servaddr;//建立一個結構體來存儲咱們要鏈接的目標服務器socket的信息
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5051); // 指定服務端的通訊端口。
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);
if (connect(sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0) // 向服務端發起鏈接清求。
{ perror("connect"); close(sockfd); return -1; }
char buffer[1024];
// 第3步:與服務端通訊,發送一個報文後等待回覆,而後再發下一個報文。
for (int ii=0;ii<3;ii++)
{
memset(buffer,0,sizeof(buffer));
sprintf(buffer,"這是第%d個超級女生,編號%03d。",ii+1,ii+1);
if (send(sockfd,buffer,strlen(buffer),0)<=0) break; // 向服務端發送請求報文。
printf("發送:%s\n",buffer);
memset(buffer,0,sizeof(buffer));
if (recv(sockfd,buffer,sizeof(buffer),0)<=0) break; // 接收服務端返回的結果。
printf("接收:%s\n",buffer);
}
// 第4步:關閉socket,釋放資源。
close(sockfd);
}
(2)客戶端向服務器端發送結構體數據而不單單是一個字符串,實際上能夠發送任意C支持的類型的數據,只要兩邊在發送和接收的時候使用一樣的數據類型來進行接收就沒有問題
socket服務器端:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
struct st_student
{
char name[50];
int age;
int height;
char id[30];
};
int main()
{
// 第1步:建立服務端的socket。
int listenfd = socket(AF_INET,SOCK_STREAM,0);
// 第2步:把服務端用於通訊的地址和端口綁定到socket上。
struct sockaddr_in servaddr; // 服務端地址信息的數據結構。
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET; // 協議族,在socket編程中只能是AF_INET。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
//servaddr.sin_addr.s_addr = inet_addr("118.89.50.198"); // 指定ip地址。
servaddr.sin_port = htons(5051); // 指定通訊端口。
if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )
{ perror("bind"); close(listenfd); return -1; }
// 第3步:把socket設置爲監聽模式。
if (listen(listenfd,5) != 0 ) { perror("listen"); close(listenfd); return -1; }
// 第4步:接受客戶端的鏈接。
int clientfd; // 客戶端的socket。
int socklen=sizeof(struct sockaddr_in); // struct sockaddr_in的大小
struct sockaddr_in clientaddr; // 客戶端的地址信息。
clientfd=accept(listenfd,(struct sockaddr *)&clientaddr,(socklen_t*)&socklen);
printf("客戶端(%s)已鏈接。\n",inet_ntoa(clientaddr.sin_addr));
// 第5步:與客戶端通訊,接收客戶端發過來的報文後,回覆ok。
char buffer[1024];
struct st_student ststudent;
while (1)
{
memset(&ststudent,0,sizeof(ststudent));
memset(buffer,0,sizeof(buffer));
if (recv(clientfd,&ststudent,sizeof(ststudent),0)<=0) break; // 接收客戶端的請求報文。
printf("接收:姓名是:%s,年齡是:%d,身高是:%d,學號是:%s\n",ststudent.name,ststudent.age,ststudent.height,ststudent.id);
strcpy(buffer,"ok");
if (send(clientfd,buffer,strlen(buffer),0)<=0) break; // 向客戶端發送響應結果。
printf("發送:%s\n",buffer);
}
// 第6步:關閉socket,釋放資源。
close(listenfd); close(clientfd);
}
socket客戶端:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
struct st_student
{
char name[50];
int age;
int height;
char id[30];
};
int main()
{
// 第1步:建立客戶端的socket。
int sockfd = socket(AF_INET,SOCK_STREAM,0);
// 第2步:向服務器發起鏈接請求。
struct hostent* h;
if ( (h = gethostbyname("192.168.31.155")) == 0 ) // 指定服務端的ip地址。
{ perror("gethostbyname"); close(sockfd); return -1; }
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5051); // 指定服務端的通訊端口。
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);
if (connect(sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0) // 向服務端發起鏈接清求。
{ perror("connect"); close(sockfd); return -1; }
char buffer[1024];
struct st_student ststudent;
// 第3步:與服務端通訊,發送一個報文後等待回覆,而後再發下一個報文。
for (int ii=0;ii<3;ii++)
{
memset(&ststudent,0,sizeof(ststudent));
ststudent.age = 18+ii;
ststudent.height = 170+ii;
sprintf(ststudent.name,"第%d個學生的姓名",ii+1);
strcpy(ststudent.id,"666");
if (send(sockfd,&ststudent,sizeof(ststudent),0)<=0) break; // 向服務端發送請求報文。
printf("發送:第%d個數據\n",ii+1);
memset(buffer,0,sizeof(buffer));
if (recv(sockfd,buffer,sizeof(buffer),0)<=0) break; // 接收服務端返回的結果。
printf("接收:%s\n",buffer);
}
// 第4步:關閉socket,釋放資源。
close(sockfd);
}
(3)一個簡單的socket實時聊天,接收客戶端輸入的文字發送給服務器端,服務器端接收消息,也能夠接收輸入的文字做爲回覆發送給客戶端。
socket服務器端:
int main()
{
// 第1步:建立服務端的socket。
int listenfd = socket(AF_INET,SOCK_STREAM,0);
// 第2步:把服務端用於通訊的地址和端口綁定到socket上。
struct sockaddr_in servaddr; // 服務端地址信息的數據結構。
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET; // 協議族,在socket編程中只能是AF_INET。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
//servaddr.sin_addr.s_addr = inet_addr("118.89.50.198"); // 指定ip地址。
servaddr.sin_port = htons(5051); // 指定通訊端口。
if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )
{ perror("bind"); close(listenfd); return -1; }
// 第3步:把socket設置爲監聽模式。
if (listen(listenfd,5) != 0 ) { perror("listen"); close(listenfd); return -1; }
// 第4步:接受客戶端的鏈接。
int clientfd; // 客戶端的socket。
int socklen=sizeof(struct sockaddr_in); // struct sockaddr_in的大小
struct sockaddr_in clientaddr; // 客戶端的地址信息。
clientfd=accept(listenfd,(struct sockaddr *)&clientaddr,(socklen_t*)&socklen);
printf("客戶端(%s)已鏈接。\n",inet_ntoa(clientaddr.sin_addr));
// 第5步:與客戶端通訊,接收客戶端發過來的報文後,回覆ok。
char buffer[1024];
while (1)
{
memset(buffer,0,sizeof(buffer));
if (recv(clientfd,buffer,sizeof(buffer),0)<=0) break; // 接收客戶端的請求報文。
printf("接收:%s\n",buffer);
memset(buffer,0,sizeof(buffer));
printf("發送:");
scanf("%s",buffer);
if (send(clientfd,buffer,strlen(buffer),0)<=0) break; // 向客戶端發送響應結果。
}
// 第6步:關閉socket,釋放資源。
close(listenfd); close(clientfd);
}
socket客戶端:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
int main()
{
// 第1步:建立客戶端的socket。
int sockfd = socket(AF_INET,SOCK_STREAM,0);
// 第2步:向服務器發起鏈接請求。
struct hostent* h;
if ( (h = gethostbyname("192.168.31.155")) == 0 ) // 指定服務端的ip地址。
{ perror("gethostbyname"); close(sockfd); return -1; }
struct sockaddr_in servaddr;
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(5051); // 指定服務端的通訊端口。
memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);
if (connect(sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0) // 向服務端發起鏈接清求。
{ perror("connect"); close(sockfd); return -1; }
char buffer[1024];
// 第3步:與服務端通訊,發送一個報文後等待回覆,而後再發下一個報文。
for (int ii=0;ii<100;ii++)
{
memset(buffer,0,sizeof(buffer));
printf("發送:");
scanf("%s",buffer);
if (send(sockfd,buffer,strlen(buffer),0)<=0) break; // 向服務端發送請求報文。
memset(buffer,0,sizeof(buffer));
if (recv(sockfd,buffer,sizeof(buffer),0)<=0) break; // 接收服務端返回的結果。
printf("接收:%s\n",buffer);
}
// 第4步:關閉socket,釋放資源。 close(sockfd);}