参考:https://www.cnblogs.com/wucongzhou/p/12498107.html
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>
int main()
{
// 第1步:创建服务端的socket。
int listenfd = socket(AF_INET,SOCK_STREAM,0);//第一个参数表示协议族,AF_INET表示是使用的ipv4。第二个参数指定socket类型,这里使用SOCK_STREAM流式,是一种适用于tcp协议的双向通信。第三个参数一般只写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 )//将上面设置的这个参数结构体绑定到socket上
{ 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)已连接。
",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
",buffer);
strcpy(buffer,"ok");
if (send(clientfd,buffer,strlen(buffer),0)<=0) break; // 向客户端发送响应结果。由于上面accept的时候获取到了连接上来的这个客户端socket,所以这里可以用这个socket向客户端返回发送消息
printf("发送:%s
",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
",buffer);
memset(buffer,0,sizeof(buffer));
if (recv(sockfd,buffer,sizeof(buffer),0)<=0) break; // 接收服务端返回的结果。
printf("接收:%s
",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)已连接。
",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
",ststudent.name,ststudent.age,ststudent.height,ststudent.id);
strcpy(buffer,"ok");
if (send(clientfd,buffer,strlen(buffer),0)<=0) break; // 向客户端发送响应结果。
printf("发送:%s
",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个数据
",ii+1);
memset(buffer,0,sizeof(buffer));
if (recv(sockfd,buffer,sizeof(buffer),0)<=0) break; // 接收服务端返回的结果。
printf("接收:%s
",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)已连接。
",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
",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
",buffer);
}
// 第4步:关闭socket,释放资源。
close(sockfd);
}