在進行socket網絡編程時, 我們需要了解一些必備的知識,例如什麼是socket,ipv4的地址結構,套接字類型等等,不然上來直接看代碼就會暈,當初學習網絡編程時,看書上的例子,總有感覺書上講的都很簡要。再或者講的原理太多把人繞暈。我這裏只想讓大家簡單知道怎麼使用socket進行網絡編程並且給出的例子可以直接使用參考。
1. 什麼是socket
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#define ERR_EXIT(m)\
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main()
{
int listenfd;
listenfd = socket(PF_INET, SOCK_STREAM, 0);
if(listenfd < 0)
ERR_EXIT("socket");
struct sockaddr_in seraddr;
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(5788);
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
int bindval = bind(listenfd, (struct sockaddr*)&seraddr, sizeof(seraddr);
if(bindval < 0)
ERR_EXIT("bind");
if((listen(listenfd, SOMAXCONN)) < 0)
ERR_EXIT("listen");
struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen);
if(conn < 0)
ERR_EXIT("accept");
char recvbuf[1024];
while(1)
{
memset(recvbuf, 0, sizeof(recvbuf));
int recvlen = read(conn, recvbuf, sizeof(recvbuf));
fputs(recvbuf, stdout);
write(conn, recvbuf, recvlen);
}
close(listenfd);
return 0;
}
client端:
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#define ERR_EXIT(m)\
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main()
{
int sockfd;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
ERR_EXIT("socket");
struct sockaddr_in seraddr;
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(5788);
seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int conn = connect(sockfd, (struct sockaddr*)&seraddr, sizeof(seraddr));
if(conn < 0)
ERR_EXIT("connect");
char recvbuf[1024];
char sendbuf[1024];
while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
write(sockfd, sendbuf, sizeof(sendbuf));
read(sockfd, recvbuf, sizeof(recvbuf));
fputs(recvbuf, stdout);
memset(sendbuf, 0, sizeof(sendbuf));
memset(recvbuf, 0, sizeof(recvbuf));
}
close(sockfd);
return 0;
}
int on = 1; //等於1代表開啓
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
ERR_EXIT("setsockopt");
9. 多個客戶端(多進程)
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#define ERR_EXIT(m)\
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
void do_service(int conn)
{
char recvbuf[1024];
while(1)
{
memset(recvbuf, 0, sizeof(recvbuf));
int recvlen = read(conn, recvbuf, sizeof(recvbuf));
if(recvlen == 0)
{
printf("clent close\n");
break;
}
if(recvlen == -1)
{
printf("read data error\n");
break;
}
fputs(recvbuf, stdout);
write(conn, recvbuf, recvlen);
}
}
int main()
{
int listenfd;
listenfd = socket(PF_INET, SOCK_STREAM, 0);
if(listenfd < 0)
ERR_EXIT("socket");
struct sockaddr_in seraddr;
memset(&seraddr, 0, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(5788);
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
int on = 1;
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
ERR_EXIT("setsockopt");
int bindval = bind(listenfd, (struct sockaddr*)&seraddr, sizeof(seraddr)
if(bindval < 0)
ERR_EXIT("bind");
if((listen(listenfd, SOMAXCONN)) < 0)
ERR_EXIT("listen");
struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
pid_t pid;
while(1)
{
int conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen);
if(conn < 0)
ERR_EXIT("accept");
printf("address:%s, port:%d\n",inet_ntoa(peeraddr.sin_addr), ntohs(pe
pid = fork();
if (pid == -1)
ERR_EXIT("fork");
if (pid == 0)
{
close (listenfd);
do_service (conn);
exit (EXIT_SUCCESS); //client close,so close subprocess
//if not closed, it is will continue
//recv connect.
}
else
{
close(conn);
}
}
close(listenfd);
return 0;
}
在這裏使用fork來開啓一個進程, 當有一個連接過來,fork一個進程去處理客戶端的連接。