简单的socket客户端
功能:连接指定的服务器,每隔1s发送一个随机数
关键字:socket,客户端,多线程,信号量,随机数
思路:
使用双线程生产消费模式,主线程消费,子线程生产,两者之前使用信号量通信。
Code:
#include <sys/types.h>
#include <sys/socket.h> /* socket */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h> /* IPV4 地址家族 */
#include <arpa/inet.h> /* inet_pton */
#include <unistd.h>
#include <stdint.h>
#include <pthread.h>
#include <semaphore.h> // 信号量
char buf[128] = {0};
sem_t sem_dataready;
static void* ProducerThread(void* arg);
static int Connect(char* serverip, uint16_t port);
int main(int argc, char** argv)
{
if (argc != 3) {
printf("\r\nError Usage!\r\n");
printf(" Usage: client <serverip> <port>");
}
pthread_t tid;
char* serverip = argv[1];
uint16_t port = atoi(argv[2]);
int cfd = Connect(serverip, port); // 连接目标服务器,返回socket描述符
write(cfd, "connect success", strlen("connect success"));
sem_init(&sem_dataready, 0, 0); // 初始化信号量
pthread_create(&tid, NULL, ProducerThread, NULL); // 创建生产者线程
while(1){ // 消费者循环
sem_wait(&sem_dataready); // 等待数据OK
send(cfd, buf, strlen(buf), MSG_DONTWAIT); // 发送随机数到服务器
}
sem_destroy(&sem_dataready);
close(cfd);
return 0;
}
static void* ProducerThread(void* arg) // 生产者子线程
{
srand(time(0));
int num;
while(1){
num = rand() % 65536;
sprintf(buf, "%d\r\n", num);
sem_post(&sem_dataready); // 通知主线程数据OK
printf("num = %d\r\n", num);
sleep(1);
}
return NULL;
}
static int Connect(char* serverip, uint16_t port)
{
struct sockaddr_in serv;
int fd = socket(AF_INET, SOCK_STREAM, 0); /* 创建socket,返回文件描述符 */
if (fd == -1){
printf("get socket fd err\r\n");
return -1;
}
serv.sin_family = AF_INET; /* 指定为IPv4地址 */
serv.sin_port = htons(port); /* 端口,主机序转网络序 */
inet_pton(AF_INET, serverip, &serv.sin_addr); /* 转换ip字符串为ipv4地址结构 */
if(connect(fd, (struct sockaddr*)&serv, sizeof(serv)) == -1){/* 使用fd发起连接*/
printf("connect failed, server not found or port incorrect\r\n");
return -1;
}
return fd;
}
编译:
$ gcc client.c -o client -lpthread
$ client 192.168.1.13 8080
运行: